面向对象的知识点
构造器
构造器的使用与作用
- 构造器在创建对象时执行-
- 构造器常用于完成对象的初始化
构造器的注意事项:
- 如果不写构造器,java会为类生成一个无参构造器
- 若我们定义了有参构造器,java就不会帮我们的类生成无参构造器了,此时需要我们自己写一个无参构造器出来
static关键字
作用范围
-
类对象和实例对象
- 类对象:用static关键字修饰,属于类,该类所有对象共享
- 实例对象:无static关键字,属于实例
-
类方法和实例方法
- 类方法:用static关键字修饰,属于类,该类所有对象共享
- 实例方法:无static关键字,属于实例
类方法和实例方法使用时的注意事项:
- 类方法可以直接访问类对象,但不能访问实例对象
- 实例方法可以直接访问类对象和实例对象
- 实例方法中可以使用this关键字,类方法中不能使用this关键字
代码块
-
类的组成:
-
代码块的分类:
-
静态代码块
格式:static{...}
特点:只会在类加载时运行一次,由于类只会加载一次,故静态代码块也只会运行一次
作用:完成对类的初始化,例如:初始化类变量
-
实例代码块
格式:{}
特点:每次创建对象时,执行实例代码块,并在构造器前执行
作用:和构造器一样,完成对象的初始化,例如:对实例变量进行初始化赋值
-
-
继承
-
继承特点
子类能继承父类的非私有成员变量和方法
-
继承后对象的创建
子类的实例对象是由子类和父类共同完成的
-
权限修饰符
-
java中只支持单继承,不支持多继承,但支持多层继承
-
方法重写
-
在子类中访问成员的特点
在子类中访问成员(变量和方法),是按照就近原则访问的:- 现在子类局部作用域范围找
- 然后在子类成员中找
- 然后在父类成员范围中找,若父类中还没找到就会报错
如果子父类中出现了重名成员,则会优先使用子类的,若此时要使用父类成员则需要加上super关键字
-
子类构造器
-
特点
子类全部的构造器,都会先调用父类的构造器,在执行自己:
子类构造器在调用父类构造器时,总是默认调用父类的无参构造器 -
子类如何实现调用父类构造器
- 在默认情况下,子类会调用父类的无参构造器,子类构造器的第一行都隐式的写了一行代码:super(),它会调用父类的无参构造器
- 如果父类中没有无参构造器,我们必须在子类每个构造器的第一行手写super(参数1, 参数2, ...),用于指定地去调用父类的有参构造器
-
通过this关键字可以调用同一个类中的其他构造器(兄弟构造器)
注意:this和super调用构造器时都只能写在第一行,因此有了this调用兄弟构造器就不能有super调用父类构造器,反之亦然
-
多态
多态是在继承/实现情况下地一种现象,表现为:对象多态、行为多态
-
多态的前提
有继承和实现关系;存在父类引用子类对象;子类重写父类方法
注意:
- 编译看左边,运行看右边
多态在编译时看等号左边的变量类型,在运行时看右边的实例对象类型 - java中多态是指对象和行为多态,Java中的成员变量不谈多态
- 编译看左边,运行看右边
-
使用多态的好处
- 在多态下,右边对象是解耦合的,便于扩展和维护
- 定义方法时,使用父类类型的形参,可以接受一切子类对象,扩展性更强,更便利
-
多态下不能使用子类独有的功能
-
多态下的类型转换
自动类型转换:父类 变量名 = new 子类(); 强制类型转换:子类 变量名 = new 父类();
-
存在继承/实现关系就可以在编译阶段进行强制类型转换,编译阶段不会报错
-
运行时,如果发现对象的真实类型和强转后的类型不同,就会报类型转换异常(ClassCastExcaption)的错误出来
People p = new Teacher(); Student s = (Student) p; Teacher t = (Teacher) p;
如上述代码,Student和Teacher都是继承于People类,变量p的之际类型是Teacher,故第二行在编译是不会报错,但在运行时会报错,第三行则正确
-
强制转换前,可以使用instanceof关键字,判断当前对象的真实类型,在考虑是否强转。
-
强制转换能够实现调用子类中的独有功能
-
final关键字
- 修饰类:该类不能被继承
- 修饰方法:方法不能被重写
- 修饰变量:变量只能被赋值一次
注意: final修饰的基本类型变量的时候,变量存储的数据不能被改变;final修饰的引用类型变量,变量存储的地址不能被改变,地址指向的对象内容可以改变
常量
使用static final修饰的成员变量被称为常量
static final SCHOOL_NAME = "西电";
可读性好,可维护性好;
程序编译时,常量会被“宏替换”:出现常量的地方全部会被替换成其常量的内容,保证在使用常量是不用再查找其内容,性能更好
抽象类(abstract)
- 修饰类就是抽象类,修饰方法就是抽象方法
- 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
- 抽象类也可以有成员变量、方法,构造器
- 抽象类不能创建对象,仅作为一种特殊的类,由子类继承并实现
- 一个类继承抽象类,则该类必须重写抽象类的所有抽象方法,否则该类也必须是抽象类
抽象类的好处:
父类的某些行为必须让子类重写,即每个子类都有改行为,但每个子类的具体情况不一样,父类就可以定义成抽象类,该行为定义成抽象方法,从而交给子类去实现,这样能够更好的支持多态
抽象类的应用场景:模板方法
-
定义一个抽象类
-
在里面定义两个方法:
一个是模板方法:把相同的代码放进去
一个是抽象方法:子类对其进行具体实现
-
模板方法建议用final关键字修饰
接口(interface)
public interface 接口名
{
// 成员变量:常量
// 成员方法:抽象方法
}
- 接口是不能直接创建对象的;接口需要被类实现(implements)的,实现接口的类称为实现类
- 一个类可以实现多个接口,实现类实现多个接口,必须重写所有接口的抽象方法,不然就要将该类定义为抽象类
- 弥补了类只能单继承的不足,一个类可以实现多个接口 让程序可以面向接口编程,这样方便在各个业务之间切换
JDK8开始,接口新增的三种形式的方法:
接口的注意事项
内部类
内部类是类中五大成分之一(成员变量、方法、构造器、内部类、代码块),如果以给类定义在另一个类的内部,则成为内部类
-
成员内部类(了解)
成员内部类相当于一个外部类的成员
-
静态内部类(了解)
-
局部内部类(了解)
是定义在方法中、代码块中、构造器等执行体中的 属于鸡肋语法,看看就好
-
匿名内部类(重点)
一种特殊的局部内部类,所谓匿名就是程序员不需要给这个类命名
枚举类
泛型
可变参数
-
可变参数是一种特殊的形式参数,定义在方法、构造器的形参列表处,它可以让方法接收多个同类型的实际参数。
-
可变参数在方法内部,本质上是一个数组
接下来,我们编写代码来演示一下
public class ParamTest{
public static void main(String[] args){
//不传递参数,下面的nums长度则为0, 打印元素是[]
test();
//传递3个参数,下面的nums长度为3,打印元素是[10, 20, 30]
test(10,20,30);
//传递一个数组,下面数组长度为4,打印元素是[10,20,30,40]
int[] arr = new int[]{10,20,30,40}
test(arr);
}
public static void test(int...nums){
//可变参数在方法内部,本质上是一个数组
System.out.println(nums.length);
System.out.println(Arrays.toString(nums));
System.out.println("----------------");
}
}
可变参数的注意事项:
-
一个形参列表中,只能有一个可变参数;否则会报错
-
一个形参列表中如果多个参数,可变参数需要写在最后;否则会报错