一、代码块
代码块定义:使用 {} 定义的一段代码。
根据代码块定义的位置以及关键字,又可分为以下四种:
- 普通代码块(定义在方法中,调试)
- 构造块(定义在类中的(不加修饰符))
- 静态块
- 同步代码块
构造块
构造块在每次产生一个新的对象就调用一次构造块。
构造块在构造方法前执行。
静态块
- 静态块优先于构造块执行。
- 无论产生多少实例化对象,静态块都只执行一次。
静态块的主要作用是对static属性进行初始化。
在主类中定义的静态块,优先于main执行
注:一个类的静态块在导入并且使用这个类时这个静态块才会使用。
类中的顺序
类属性、对象属性、静态块、构造块、构造方法、静态方法、普通方法。
外部类属性格式:外部类名.this.属性/方法()
注:外部类不能访问内部类的成员属性和方法。
二、内部类
内部类可以访问外部类的成员属性和方法。
访问外部类属性格式:
外部类名.this.属性/方法()
外部类不能访问内部类的成员属性和方法。
内部类为什么存在?
- 内部类方法可以访问该类定义所在作用域中的数据,包括被 private 修饰的私有数据。
- 内部类可以对同一包中的其他类隐藏起来。
- 内部类可以实现 java 单继承的缺陷。
- 当我们想要定义一个回调函数却不想写大量代码的时候我们可以选择使用匿名内部类来实现。
内部类与外部类的关系:
- 对于非静态内部类,内部类的创建依赖外部类的实例对象,在没有外部类实例之前是无法创建内部类的。
- 内部类是一个相对独立的实体,与外部类不是is-a关系(从属关系)。
- 内部类可以直接访问外部类的元素(包含私有域),但是外部类不可以直接访问内部类的元素。
- 外部类可以通过内部类引用间接访问内部类元素。
如何实例化一个内部类的对象?
有如下两种方法:
- 类名:外部类.内部类
- 持有一个外部类的实例化对象
如:
方法一:
Outer.Inner inner = new Outer().new Inner();
方法二:
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
一个内部类创建成功后持有这个内部类所在外部类的对象。
内部类分类
成员内部类
1. 成员内部类中不能存在任何static的变量和方法
2. 成员内部类是依附于外部类的,所以只有先创建了外围类才能够创建内部类
静态内部类
- 静态内部类的创建是不需要依赖于外围类,可以直接创建
- 静态内部类不可以使用任何外围类的非static成员变量和方法,而内部类则都可以要实例化一个静态内部类的对象:
外部类.内部类 内部类对象 = new 外部类.内部类();
方法内部类 - 局部内类不允许使用访问权限修饰符 public private protected 均不允许
- 局部内部类对外完全隐藏,除了创建这个类的方法可以访问它其他的地方是不允许访问的。
- 局部内部类要想使用方法形参,该形参必须用final声明(JDK8形参变为隐式final声明)。
匿名内部类 - 匿名内部类是没有访问修饰符的。
- 匿名内部类必须继承一个抽象类或者实现一个接口
- 匿名内部类中不能存在任何静态成员或方法
- 匿名内部类是没有构造方法的,因为它没有类名。
- 与局部内部相同匿名内部类也可以引用方法形参。此形参也必须声明为 final
三、继承的定义与使用
对类进行扩展,开闭原则(OCP):对外扩展开放,对修改关闭
- 单继承
- 子类继承父类所有结构(属性、方法等),但是能不能使用,取决于访问控制符。
- 如果子类和父类定义了相同的方法(覆写),调用子类的用this.方法名(),调用父类的用super.方法名(),调用构造方法用super()。
- 子类可以实例化给父类,父类不能实例化给子类。
- 实例化子类对象时,先调用父类构造方法,再调用子类构造方法
- 如果父类里面没有提供无参构造方法,此时默认调用super();在子类的构造参数中要显式调用。
在子类调用父类的构造方法中,有两种方法:
(1)显式调用
super(参数);
(2)隐式调用
super(无参);
this.setName(参数);
子类又被称为派生类,父类又被称为超类。
语法:
class 子类 extends 父类
多层继承
层数不允许太深,最多三层。
隐式继承
父类中都用private修饰的,子类中只能使用非private修饰的,而所有的private操作无法被直接使用,所以称为隐式继承。
四、覆写
方法的覆写
如果子类和父类定义了相同的方法名,参数列表,则子类可以对父类中的该方法进行覆写。
注:子类覆写的方法访问控制权限比父类的方法更宽泛(大)。
注:
- 你当前使用的对象是通过哪个类new的,就用的是哪个类。
- 当调用某个方法,如果该方法已经被子类所覆写了,那么调用的一定是被覆写过的方法。
- 如果在父类方法使用private定义,子类中使用public覆写,不属于覆写。
java中权限的范围
public > protected > [default package] > private
重载和覆写的区别
区别 | 重载(overload) | 覆写(override) |
---|---|---|
概念 | 方法名称相同,参数的类型及个数不同 | 方法名称、返回值类型、参数的类型及个数完全相同 |
范围 | 一个类 | 继承关系 |
限制 | 没有权限要求 | 被覆写的方法不能拥有比父类更严格的访问控制权限 |
属性的覆写
当子类定义了和父类属性名称完全相同的属性的时候,就成为属性的覆写。
按照就近取用原则,如果子类中有就在子类中用,如果子类没有,就去父类中找。
this和super的区别
区别 | this | super |
---|---|---|
概念 | 访问本类中的属性和方法 | 由子类访问父类中的属性、方法 |
查找范围 | 先查找本类,如果本类没有就调用父类 | 不查找本类而直接调用父类定义 |
特殊 | 表示当前对象 | 无 |
五、final关键字
final被称为终结器。
- 使用final修饰类、方法、属性
- final成员变量必须在声明的时候初始化或者在构造器中初始化,否则就会报编译错误
- 使用final定义的类不能有子类(String类便是使用final定义)。
- final一旦修饰一个类之后,该类的所有方法默认都会加上final修饰。(不包含成员变量)。
- 使用final定义的方法不能被子类所覆写。
- 使用final定义的变量就成为了常量,常量必须在声明时赋值,并且不能够被修改。
- 使用final修饰的变量不能再次赋值。
- 定义常量(public static final ),常量全用大写字母,多个单词间以_分隔。
六、多态性
方法的多态性:
- 方法的重载:同一个方法名称可以根据参数的类型或个数不同调用不同的方法体
- 方法的覆写:同一个父类的方法,可能根据实例化子类的不同也有不同的实现
对象的多态性:(抽象类和接口)
- 向上转型:自动,父类 父类对象 = 子类实例。
- 向下转型:强转,子类 子类对象 =(子类)父类实例
向下转型需要判断:
对象 instanceof 类型
返回值是boolean 如果对象是由类型实例化的但会true,否则false