03Java面向对象
2022/1/20 22:11:33
本文主要是介绍03Java面向对象,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
面向过程和面向对象的设计思想
面向过程:是一种程序设计思想。C语言
解决问题时,是按具体的实现步骤一步一步实现。
面向过程直接关注流程。
eg. 首先 开门()
其次 装大象()
最后 关门()
面向对象:是一种程序设计思想。Java、Python,C++,C#
以分类的方式进行思考和解决问题。
先对整体关系进行分类,根据不同的类深入细节的处理。
符合人类认知习惯。
-
面向对象 —> 使用对象 对象是什么 对象从何而来
-
面向对象实现:对客观事物进行分类(设计类/发现类 类是抽象的),实际使用时,需要以类为模板创建出一 个个具体的对象。
人类 —> 张三(对象)
设计一个冰箱类(抽象的)
public class 冰箱{
名字
型号
价格
开门();
装大象;
关门();
}
冰箱 bx = new 冰箱(); //bx表示这个对象,在运行时在内存中会划出一块空间,用来存储具体的对象。
bx.开门(); //具体的对象
冰箱.开门(); //错误 冰箱是一个概念
面向对象是在宏观整体上对事物之间的关系进行设计,具体实现又回归到面向过程的具体实现,两者是相辅相成的。
什么是类
类是一个模板,是对同一类事物属性(名词)和行为(动词)的抽象。
类是有地址的,包就是其地址。
类是一个模板,它是
类的结构:
-
成员变量:事物属性的描述。名词 属性
成员变量在定义是,可以对其初始化,也可以不进行初始化,java会在构造方法中对其进行默认赋值 。 引用类型值为:null int:0 float:0.0 char:‘ ’ boolean:false
局部变量需要自己对其初始化。
创建对象时,会从类中向对象中复制一份成员变量 到对象中
成员变量可以被 方法,构造方法,代码块所访问
-
成员方法:事物的行为。(可以做的事情) 动词 行为
-
构造方法:初始化对象。 有专职作用 初始化对象
-
内部类:即在类体中声明的类。
-
代码块:一段没有名称的代码。
类的定义:
- 发现类
- 发现类的共有属性(成员变量)
- 发现类的方法
以类为模板创建对象 使用对象。
万事万物(实际存在的事物 具体) 皆为对象
//Car.java /*发现类 汽车类 * public(访问权限修饰符) class(关键字修饰类) Car(类名) * { * 类体 * 成员变量 * 成员方法 * 构造方法 * }*/ public class Car { /* 定义类的成员变量 名词 属性 直接定义在类中,所以成为类的成员 可以使用java所支持的任意的数据类型 基本类型、引用类型 */ String name; //引用类型 String color; float price; //基本类型 /* 定义类的成员方法 动词 行为 */ public void run(){ System.out.println(this.name+"汽车行驶"); } public void stop(){ System.out.println(name+"汽车停止"); } }
什么是对象
对象是类的一个实例,是以类为模板在内存中创建的实际存在的实例。
//TestCar.java public class TestCar { public static void main(String[] args) { /* 类是模板,是抽象概念 就是一个定义 对象是具体,可以直接被使用的,是以类为模板,在内存中创建出来的实际存在的实例 */ Car bm = new Car(); bm.name = "宝马"; bm.color = "黑色"; bm.price = 200000; System.out.println(bm.name); bm.run(); bm.stop(); Car bc = new Car(); bc.name = "奔驰"; bc.color = "黑色"; bc.price = 2043000; System.out.println(bc.name); bc.run(); bc.stop(); } }
对象的创建和使用:
-
Car bm = new Car();
-
Car() 构造方法 构造方法的名字与类名相同new Car() new 关键字,创建对象。
以Car类为模板,在内存中创建一个具体实例 将类这个模板中的成员向具体对象中复制一份,每个对象中都是独一无二的。
-
Car bm/bc 声明了一个类型为Car的变量 。
-
= 将右边的对象地址赋值给左边的变量,左边的变量就在程序中表示内存中的对象。
-
同一类的每个对象有不同的成员变量存储空间。
-
同一类的每个对象共享该类的方法。
类和对象
类是一类事物的抽象概念,是一个模型。
对象是由这个模型所创造的一个个具体存在的,实实在在存在的实例。所以创建对象的过程也叫实例化对象。
现实生活中先有对象后有类,而编程时先设计类后创建对象。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T07lZ2qF-1642687013926)(E:\Java学习\2022-1-16java第三章面向对象1\课件\创建对象简图.png)]
构造方法
特点:构造方法名与类名相同,且没有返回值,且不需要void修饰。
作用:在构造方法中为创建的对象初始化赋值。
每次创建对象时,至少要调用一个构造方法,一个类中可以有多个构造方法
每个类都有构造方法。如果没有显式地为类定义构造方法,Java将会为该类提供一个默认构造方法,但是只要在一个Java类中定义了一个构造方法后,默认的无参构造方法即失效。
一个类可以有多个构造方法。
//Car.java public class Car { String name; String color; float price; /* 类中默认的无参构造方法,默认是有的, 如果没有显示的写出来,如果定义了有参的构造方法,那么无参的就会被覆盖 以后一般情况下,定义了有参的构造方法,最好把无参显示定义出来 */ public Car(){ //在无参构造方法中,可以使用默认值为对象中的属性赋值 //引用类型:null 整数:0 浮点:0.0 char:‘ ’ boolean:false } public void run(){ System.out.println(this.name+"汽车行驶"); } public void stop(){ System.out.println(name+"汽车停止"); } }
//TestCar.java public class TestCar { public static void main(String[] args) { /* new Car() ---> 构造方法 特点:构造方法名与类名相同,且没有返回值,且不需要void修饰 作用:在构造方法中为创建的对象初始化赋值 每次创建对象时,至少要调用一个构造方法,一个类中可以有多个构造方法 */ Car bm = new Car(); bm.name = "宝马"; bm.color = "黑色"; bm.price = 200000; bm.run(); } }
方法的重载
在一个类中有多个方法名称相同的现象。
构造方法,成员方法都可以重载。
如何区分方法:
- 通过方法参数个数区分
- 通过类型区分
- 通过顺序区分
调用时,会根据不同的参数表选择对应的方法。
注意:方法重载跟方法的返回值类型没有任何关系。
重载的作用:扩展方法功能。
//构造方法 public Car(){ //在无参构造方法中,可以使用默认值为对象中的属性赋值 //引用类型:null 整数:0 浮点:0.0 char:‘ ’ boolean:false } public Car(String name,String color,float price){ //this表示当前正在被使用的对象 this.name = name; //此name是成员变量中的name this.color = color; this.price = price; } //构造方法 public Car(String name,String color){ this.name = name; //此name是成员变量中的name this.color = color; } public Car(float price,String name,String color){ //this表示当前正在被使用的对象 this.name = name; //此name是成员变量中的name this.color = color; this.price = price; } //成员方法 public void run(){ System.out.println(this.name+"汽车行驶"); } public void run(int speed){ System.out.println(this.name+"汽车以"+speed+"速度行驶"); }
public class TestCar { public static void main(String[] args) { Car bm = new Car(); bm.name = "宝马"; bm.color = "黑色"; bm.price = 200000; bm.run(); Car bc = new Car("奔驰","红色",300000); bc.run(); Car dz = new Car("大众","红色"); dz.run(120); } }
对象与引用
java中除了8种基本类型外,其余的都是引用类型。
基本类型:使用关键字声明,结构简单。
int a = 10;
引用类型:类、数组、结构……
类是符合类型,比较复杂可以定义更多的东西
Car dz = new Car("大众","红色"); Car ad = dz; //创建了2个对象 ad、dz指向相同的对象 ad.name = "奥迪"; System.out.println(ad.name); //奥迪 System.out.println(dz.name); //奥迪 System.out.println(bc.name); //奔驰
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Desjw9nZ-1642687013933)(E:\Java学习\2022-1-17java第三章面向对象2\课件\对象创建内存图.png)]
值传递与引用传递
严格来讲,参数传递只有值传递
为了基本类型和引用类型区分:分为值传递和引用传递
-
值传递特指基本类型。
方法调用时,实际参数把它的值传递给 对应的形式参数,形式参数只是用实际参数的值初始化自己的存储单元内容,是两个不同的存储单元,所以方法执行中形式参数值的改变不影响实际参数的值。
public class TestValue { public static void main(String[] args) { int a = 10; TestValue t = new TestValue(); t.test(a); System.out.println("a:"+a); //a的值是多少? 10 } /* 基本类型就是值传递 */ public void test(int b){ System.out.println("b:"+b); //10 b = 20; } }
-
引用传递对应的是引用类型。
也称为传地址。方法调用时,实际参数是对象,这时实际参数与形式参数指向同一个地址,在方法执行中,对形式参数的操作实际上就是对实际参数的操作,这个结果在方法结束后被保留了下来,所以方法执行中形式参数的改变将会影响实际参数。
public class TestValue { public static void main(String[] args) { TestValue t = new TestValue(); Car car1 = new Car(); car1.name = "奔驰"; t.test(car1); System.out.println("car1.name:"+car1.name); //大众 } /* 引用类型 传递的不是对象本身,而是传递对象的引用地址 */ public void test(Car car2){ System.out.println("car2.name:"+car2.name); //奔驰 car2.name = "大众"; } }
基本类型传递的是该数据值本身。引用类型传递的是对对象的引用,而不是对象本身 。
this关键字
this关键字代表当前正在使用的对象。
static关键字
static被称为静态,可以用来修饰类的属性,方法,代码块,内部类。
- 随着类的加载而加载
- 优先于对象存在
- 修饰的成员,被所有对象共享
- 可不创建对象,直接被类调用。
静态属性是类的所有对象共享的,即不管创建了多少个对象,静态属性在内存中只有一个。
public class Aodi { /* Aodi 他们的名字应该都叫奥迪,在定义类的时候直接对其进行赋值。 型号和价格是不一样的 */ String model; float price; //static修饰的成员变量在内存中只有一份,所有对象可以共享,随着类的加载而加载,通过类名调用 static String name = "奥迪"; }
public class TestAodi { public static void main(String[] args) { System.out.println(Aodi.name); //可以不创建对象,直接被类调用 Aodi a8 = new Aodi(); a8.model = "a8"; a8.price = 300000; System.out.println(Aodi.name+":"+a8.model+":"+a8.price); //可通过类名直接调用 Aodi q8 = new Aodi(); q8.model = "q8"; q8.price = 500000; System.out.println(q8.name+":"+q8.model+":"+q8.price); } }
static方法可以使用对象调用,也可以直接用类名调用,建议用类名直接调用 。
在static方法内部只能访问类的static属性,不能访问类的非static属性,static属性先加载。
静态的成员随着类加载后,就可以使用了。而非静态的必须要创建对象后,才可以使用。
//static 修饰的方法是静态方法,属于类,只能使用静态的成员变量。 public static void run(){ System.out.println(name); System.out.println(this.model); //报错 非静态创建对象后才能使用 } //可以直接使用 Aodi.run();
代码块
代码块在类中声明,类似于没有名称的方法体。
类加载时就自动执行。
分为实例代码块,静态代码块。
- 实例代码块:在创建对象时调用。
- 静态代码块:在类加载时调用,只调用一次(因为类只加载一次)。
{ System.out.println("实例代码块1"); } { System.out.println("实例代码块2"); } /* 以后,把在类加载时,就需要自动执行的内容,写在静态代码块中,只执行一次 */ static { System.out.println("静态代码块1"); } static { System.out.println("静态代码块2"); }
public class Test { public static void main(String[] args) { new Aodi(); //第一次创建对象,并加载类 new Aodi(); //第二次创建对象,不加载类 } }
//静态代码块有限执行,且执行一次。 //原因:类比对象优先加载,且只加载一次 /*输出结果为: 静态代码块1 静态代码块2 实例代码块1 实例代码块2 实例代码块1 实例代码块2 */
包
包:为了更好的管理java中的类,创建包来进行管理,用于区别类名的命名空间。
包在硬盘上来讲其实就是文件夹,但在java项目中和文件是有区别的,是作为类的路径存在的。
directory:文件夹 package:包
同一个包下,不会有两个相同的类名。
包的作用:
-
避免类重名 (区别重名类)
package Day3; //import 使用其他包中的类时,需要导入其他包中的类(同一个包的类、java.lang包不用导入) import Day2.Car; public class Test { public static void main(String[] args) { String s; //java.lang包 /* Car是类的简称 类的全称(全类名)Day2.Car */ new Car(); //Day2包里的Car new Day1.Car(); //Day2中的Car已导入,只能使用全类名 } }
-
按照不同功能管理类
eg. 控制层、数据访问层、业务逻辑处理层、公共类、配置类、工具类等
-
控制访问权限
访问权限修饰符(见下个标题)
包的命名规范:在包名中,可以使用 . 号来区分包的级别,包名一般情况下是小写 。
- 第一级 指该项目的类型,如com(商业公司),org(组织),gov(政府),edu(教育)等,
- 第二级 指项目所开发或者运行的公司名称,如:oracle,sun,huawei 等
- 第三级 指项目的名称,如:bcms,oa,erp,cms等
- 第四级 指项目模块的名称,如:bean,action,exception等
访问权限修饰符
按照不同功能管理类
控制访问权限
Java语言有四个权限访问修饰符,权限从大到小依次为:
- public :公共权限 修饰类、属性、方法。可以被任意类访问
- protected:受保护的权限 修饰属性、方法。 可以被同包类访问,如果不是同包类,必须是该类的子类才可以访问。
- default:同包权限 修饰类、属性、方法。只能被同包的类访问
- private:私有权限 修饰属性、方法。 只能在本类中访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ubA98y4u-1642687013940)(E:\Java学习\访问权限修饰符.png)]
package com.ffyc.javaoop.day3; /* 类 只能用public 和 默认 修饰 */ public class Demo { /* public 公共权限 在任何类中都可以访问到 protected 受保护权限 在自己类中,同包的其他类中,不同包的子类中可以访问到 默认权限 在自己类中,同包的其他类中 private 私有权限 只能在自己类中访问到 */ public String pubName; protected String proName; String delname; //默认 private String priName; protected void test1(){ } protected void test2(){ } void test3(){ } private void test4(){ } public void test(){ Demo d = new Demo(); d.pubName = "p"; d.proName = "po"; d.delname = ""; d.priName = "pi"; } }
package com.ffyc.javaoop.day3.child; import com.ffyc.javaoop.day3.Demo; public class ChildDemo extends Demo{ public void test(){ Demo d = new Demo(); d.pubName = "a"; //只剩下公共的 ChildDemo cd = new ChildDemo(); //默认权限和私有权限仍访问不到 cd.proName = "1"; cd.pubName = "q"; } }
package com.ffyc.javaoop.day3; public class Demo1 { public void test(){ Demo d = new Demo(); d.pubName = "a"; d.proName = "p"; d.delname = "d"; } }
面向对象的三大特征
面向对象语言的三大特征:
- 封装
- 继承
- 多态
封装
封装:将某个功能封装成一个方法。eg. 写了一个工具类,定义好了几个常用的方法。
面向对象中的封装:是隐藏(访问权限修饰符 private、protected、默认、public……)将类中的某些信息不对外开放。
private String name; //属性私有化,只是封装的一种表示
封装特点:
- 隐藏类的实现细节
- 方便加入控制语句
- 只能通过规定方法访问
- 方便修改实现
package com.ffyc.javaoop.day3.pack; public class Person { private String name; private int age; public void setAge(int age){ if(age>18){ this.age = age; //this.age对象中的age } } public int getAge(){ return age; } //setXXX方法就是为私有属性提供访问的公共方法 public void setName(String name){ //方便加入控制语句 if(name.length()>3 && name.length()<6){ this.name = name; } } public String getName() { return this.name; } }
package com.ffyc.javaoop.day3.pack; public class TestPerson { public static void main(String[] args) { //private 将name属性隐藏,在其他类中无法访问 Person zs = new Person(); // zs.name = "fadsf"; zs.setName("fsdfj"); System.out.println(zs.getName()); } }
单例模式:(模式就是模板,解决一种问题,就有)
单例模式解决在一个程序中,只能让一个类创建一个对象。
package com.ffyc.javaoop.day3.pack; public class WindowDemo { static WindowDemo windowDemo = null; /* 将构造方法私有化,这样在其他类中就不能创建对象了 */ private WindowDemo(){ } //向外提供一个方法,用来创建唯一的一个对象,并返回此对象 public static WindowDemo getWindowDemo(){ //单例模式 //第一次已经创建,第二次windowDemo不为null,因而直接返回windowDemo if(windowDemo == null){ windowDemo = new WindowDemo(); } return windowDemo; } }
package com.ffyc.javaoop.day3.pack; public class TestWindow { public static void main(String[] args) { // new WindowDemo(); 构造方法私有,无法创建对象 System.out.println(WindowDemo.getWindowDemo()); System.out.println(WindowDemo.getWindowDemo()); } }
继承
继承:是面向对象程序设计不可缺少的设计思想,实现代码可重用,提高代码可扩展性的主要途径。
什么时候使用继承:
-
可以把一些共有属性行为抽取出来,创建一个父类,让其他类继承即可。
eg. 猫是动物 狗是动物 是属于同一类 大小的关系
基本语法:
- 父类 —> 子类
- 子类 extends 父类 extends Object
public class Animal extends Object{ private String name; private int age; public void eat(){ System.out.println(this.name+"动物吃东西"); } //get set方法 专属用于私有属性赋值 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } /* 子类继承父类 使用extends关键字 一个类只能直接继承一个父类,但是可以间接继承 */ public class Dog extends Animal{ } public class AngelDog extends Dog{ //扩展字节的功能,同时重复调用父类的功能 public void fly(){ System.out.println("哮天犬会飞"); } }
public class Test1 { public static void main(String[] args) { Dog dog = new Dog(); dog.setName("可可"); dog.setAge(5); System.out.println(dog.getName()); System.out.println(dog.getAge()); dog.eat(); } }
继承是从已有的类中派生出新的类,新的类能吸收已有类的属性和行为,并能扩展新的能力。
- 在JAVA中使用extends关键字来表示继承关系。
- JAVA不支持多继承,单继承使JAVA的继承关系很简单,一个类只能有一个直接父类。
- 继承之后子类可以调用父类的所有非私有属性和非私有方法
符合is-a关系的设计,使用继承。将子类共有的属性和行为放到父类中。
继承的传递性:
- C类从B类继承,B类又从A类继承,那么C类就具有B类和A类的所有非私有属性和非私有方法。
- 当一个没有显示的继承任何一个类时,那么jvm会默认让类继承Object类,Object(java.lang包)是所有类的基类(父类/超类)。
继承中的构造方法:
-
在创建对象,调用构造方法时,子类的构造方法会默认去调用父类的构造方法。因为要先初始化父类,子类才可以去使用父类中的属性行为。
构造方法可以用来初始化
-
使用super关键字调用父类任意一个构造方法,必须写在构造方法的第一行。
-
如果子类的构造方法中没有显式地调用基类构造方法,则系统默认调用基类无参数的构造方法。
public class AngelDog extends Dog{ //扩展字节的功能,同时重复调用父类的功能 public void fly(){ System.out.println("哮天犬会飞"); } public AngelDog(){ //super表示父类,并不是父类对象 //super()调用父类构造方法,默认存在,可以不写,在子类构造方法的第一行 //如果显示的调用,必须在第一行调用 super(); System.out.println("AngelDog类无参构造"); } }
super关键字用途:
-
使用super关键字访问父类成员。
-
用super.成员变量名来引用父类成员变量。
-
用super.方法名(参数列表)访问父类的方法。
-
用super.构造方法(参数列表)访问父类构造方法。
-
注:不要把super误认为是父类对象.在创建子类对象时, 不会创建父类对象,只会将父类中的信息加载到子类对象中存储。
public AngelDog(){ //super表示父类 super(); System.out.println("AngelDog类无参构造"); super.eat(); }
方法的重写:当父类的方法实现不能满足子类需求时,可以对方法进行重写(override)。
-
重写要求:与类中的方法名一致,参数、返回值一致,访问权限等于或大于父类权限。
-
@Override 是java中的注解标签 用来标记的。作用在方法上,用来表示此方法是从父类中重写而来的,在编译期间检测语法格式。
/* 神犬吃东西实现方式与其他动物不一样,那么就可以在哮天犬类中重写(覆盖)Animal类中的eat()方法 方法重写 重写的要求:与父类中的方法名一致,参数、返回值一致 访问权限等于或大于父类权限 @Override 是java中的注解标签,用来标记的 @Override 作用在方法上,表示此方法是从父类中重写而来的,在编译期间检测语法格式。 */ @Override public void eat(){ System.out.println("哮天犬坐着吃饭"); }
多态
同一种事物,在不同时刻表现不同的状态 。
前提:要有继承(包括接口实现),要有方法重写,父类的引用指向子类对象。
//父类的引用指向子类对象 Animal dog1 = new Dog(); Animal cat1 = new Cat(); Object d = new Dog(); Dog dog = new Dog(); //Dog的引用指向Dog对象 Cat cat = new Cat();
编译期间:写代码时就是编译期间,Animal dog1 在编译期间是Animal类型。
运行期间:run运行程序。Animal dog1 在运行期间是Dog类型。
对于成员方法来讲,编译看左边,运行看右边。
对象在运行时才创建。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JD3FJj9a-1642687013942)(E:\Java学习\2022-1-19java第三章面向对象4\课件\Snipaste_2022-01-19_11-26-24.png)]
对于静态方法来讲,编译和运行都看左边。
对于成员变量来讲,编译和运行都看左边。
多态:提高了程序的扩展性,因而子类类型向上转为父类类型。
多态存在不足:使用多态时,不能访问子类中特有的方法,因为已经向上转为父类类型,编译期间不能调用子类特有方法。
解决:需要向下转型,转型前最好判断类型,使用instanceof关键字来判断。
public class Test2 { public static void main(String[] args) { /* 创建一个喂不同动物,动物吃东西的功能。 不用多态来实现,扩展性不好。 */ Dog dog = new Dog(); Cat cat = new Cat(); Test2 t = new Test2(); t.feedDog(dog); t.feedCat(cat); } public void feedDog(Dog dog){ dog.eat(); } public void feedCat(Cat cat){ cat.eat(); } }
public class Test3 { public static void main(String[] args) { /* 创建一个喂不同动物,动物吃东西的功能。 用多态来实现。 把子类类型上升为父类类型,可以用父类类型表示所有的子类对象 (多态的好处) */ Animal dog = new Dog(); Animal cat = new Cat(); Test3 t = new Test3(); t.feedAnimal(dog); t.feedAnimal(cat); } public void feedAnimal(Animal animal){ animal.eat(); // animal.play(); animal中无play()方法因而报错,需要向下转型 // Dog dog = (Dog) animal; // dog.play(); //Cat类中无play()因而cat报错 //向下类型转换时,需要做一个判断 //关键:instanceof 检测animal在运行时,实际的类型是否为Dog,如果是返回true,否则返回false。 if(animal instanceof Dog){ Dog dog = (Dog)animal; dog.play(); } } }
抽象类
抽象就是一个概念,不是具体的。
抽象方法:
- 抽象方法是一种特殊的方法:它只有声明,而没有具体的实现。
- 抽象方法必须用abstract关键字进行修饰。
- 在一些体系结构比较庞大的体系中,可以将顶层的类中的方法定义为抽象的。
抽象类:
-
如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
-
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法。
-
用abstract修饰的类就是抽象类。如果某个类中包含有抽象方法,那么该类就必须定义成抽象类
/* 如果一个类中有抽象的方法,name这个类必定是抽象类 但是抽象类中不一定有抽象方法 抽象类就是一个不完整的类,里面有抽象方法 抽象类因为没有具体实现的抽象方法,所以抽象类不能创建对象,除了不能创建对象外,其他功能和正常类一致。 */ public abstract class Animal { private String name; int age; /* abstravt 修饰的方法是抽象方法,可以没有具体的实现 只是作为一个功能的定义,在顶层类中往往只需要定义功能即可,让其他类去实现 */ public abstract void eat(); public Animal(){ } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } /* 一个类继承了抽象类,可以继续声明成抽象类 */ public abstract class Dog extends Animal{ private String type; public String getType() { return type; } public void setType(String type) { this.type = type; } } /* 哮天犬就是一个具体的类,重写父类中的抽象方法 */ public class AngelDog extends Animal{ @Override public void eat(){ System.out.println("哮天犬坐着用餐"); } }
public class Test { public static void main(String[] args) { AngelDog xtq = new AngelDog(); xtq.setAge(1000); //非抽闲的依旧可以调用 xtq.eat(); } }
抽象类特点:
- 抽象类不能被实例化,但可以有构造方法。因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象。
- 抽象类只能用作基类,表示的是一种继承关系。继承抽象类的非抽象类必须实现其中的所有抽象方法,而已实现方法的参数、返回值要和抽象类中的方法一样。否则,该类也必须声明为抽象类。
final关键字
final用于声明属性、方法和类。
-
属性:final修饰的属性是常量,值不可以改变,必须要初始化赋值。
//在定义时,直接为其赋值,值不可以改变。建议使用static赋值,在整个内存中值只有一份。 static final int num = 100; //在定义时,没有为常量赋值,必须在构造方法中赋值。在每一个对象中,都可以拥有一个常量。 final int count; //创建一个有参的构造方法 public finalDemo(int count) { this.count = count; } public void test(){ // num = 10; //final修饰无法赋值 new String("abc"); //只有创建对象时,在其构造方法中为其赋值。 new finalDemo(10); new finalDemo(20); }
-
方法:final修饰的方法不能被子类重写,不能修饰抽象的方法。
public final void test(){ //final修饰的方法不能被子类重写 }
-
类:修饰后的类不能被继承,final不能修饰抽象类、接口。
接口
接口(USB接口):专注于功能的设计,而不是实现。让其他类去具体实现即可。与抽象类类似,但有区别。
基本语法:
- 接口中所有属性默认为:public static final 静态常量
- 抽象方法默认:public abstract 修饰
- jdk8以后添加了静态方法,接口可以直接调用。
- jdk8以后添加了默认方法,通过子类调用。
public interface Myinterface { // public static final int NUM = 10; //必须赋值 NUM常量 前面默认有public static final int NUM = 10; //接口种定义的属性默认是静态常量 // public abstract void eat(); 前面默认是public abstract修饰 void eat(); void sleep(); //java8之后,新增加两种方法(静态方法,默认方法) //静态方法 接口自己调用 public static void test1(){ System.out.println("test1 "+NUM); } //默认方法 是让子类重写,或者让子类调用 public default void test2(){ System.out.println("test2"); } } public class Test { public static void main(String[] args) { System.out.println(Myinterface.NUM); Myinterface.test1(); //静态方法 // Myinterface.test2(); 默认方法无法直接调用 } }
接口的继承:
- 一个类只能直接继承一个类
- 一个类可以实现多个接口
- 一个接口可以继承多个接口
public class MyinterfaceImpl extends Object implements Myinterface,InterfaceC{ //MyinterfaceImpl :Myinterface类的名字,Impl接口的实现 //静态方法不能重写,默认方法可重写可不重写 /* 一个类实现接口,要么将此类继续声明为抽象类;要么重写接口中的所有抽象方法。 */ @Override public void eat() { } @Override public void sleep() { } //默认方法可重写可不重写 @Override public void test2() { } } public interface Myinterface extends InterfaceA,InterfaceB{}
接口的特性:
- 接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字
- 接口中方法可以是抽象的,静态的,默认的
- 接口中声明的属性默认为 public static final 的
- 接口不是被类继承了,而是要被类实现
- 接口不能实例化对象,无构造方法
- 一个类可以实现多个接口
- 与继承关系类似,接口与实现类之间存在多态性
- 一个接口能继承其它多个接口
- 当类实现接口的时候,类要实现接口中所有的抽象方法。否则,类必须声明为抽象的类
抽象类和接口的区别
相同点:
- 都不能创建对象
- 都可以表示多态性
不同点:
- 接口
- 接口不能有构造方法
- 不能有成员变量
- 不能有成员方法,只有静态方法、默认方法
- 抽象类
- 能有构造方法
- 能有成员变量
什么时候使用接口,什么时候使用抽象类:
public abstract class Animal { private String name; public Animal(){ } public Animal(String name ){ this.name = name; } public abstract void eat(); public abstract void sleep(); public String getName() { return name; } public void setName(String name) { this.name = name; } } public class Bird extends Animal implements CanFly,CanCry{ @Override public void eat() { } @Override public void sleep() { } @Override public void cry() { } @Override public void fly() { } } public class Dog extends Animal{ @Override public void eat() { } @Override public void sleep() { } } public interface CanCry { void cry(); } public interface CanFly { void fly(); } public class Test { public static void main(String[] args) { Animal bird = new Bird(); CanFly b = new Bird(); //接口也可以作为父类类型来存在 CanCry c = new Bird(); // CanCry d = new Dog(); Dog没有CanCry的接口,无法实现 } }
这篇关于03Java面向对象的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-26JavaScript入门教程:从零开始学习JavaScript编程
- 2024-12-26JavaScript入门教程:从零开始学习JavaScript
- 2024-12-26JS编程入门指南:从零开始学习JavaScript
- 2024-12-25Java编程面试题详解与解答
- 2024-12-25TS基础知识详解:初学者必看教程
- 2024-12-252024面试题解析与攻略:从零开始的面试准备指南
- 2024-12-25数据结构与算法学习:新手入门教程
- 2024-12-25初学者必备:订单系统资料详解与实操教程
- 2024-12-24内网穿透资料入门教程
- 2024-12-24微服务资料入门指南