final关键字:
代表最终不可变的。
用法:
1、用来修饰一个类:不能有子类,所以其中所有的方法都不嗯呢该被覆盖重写。
2、用来修饰一个方法:方法不能被覆盖重写。
3、用来修饰一个局部变量(Variable):一次赋值,终生不变。
4、用来修饰一个成员变量:一次赋值,终生不变。没有默认值需要手动赋值。
final
修饰的类又叫“太监类”。
final关键字
和abstract关键字
冲突,不能同时是使用。
格式:
public final class 类名{
//类内容
}
final用来修饰一个局部变量,那这个局部变量,一次赋值终生不变。
final int numb = 15;
System.out。println(numb);// 15
注意:
final修饰引用类型的数据,地址值不可变,但是通过地址修改内部的内容是可以的。
final修饰基本类型,一次赋值,终生不变。
final用来修饰一个成员变量,也是一次赋值,终生不变。
成员变量本来是默认值的。一旦final修饰了成员变量,那么将不再具有默认值。
成员变量赋值:
1、直接定义的时候赋值。
2、通过构造方法赋值。
final int numB = 15;
System.out.println(numB); // 15
// numB = 20; // 错误写法!
// numB = 15; // 错误写法!
final int numC;
numC = 25; // 分成两步,是正确写法!
System.out.println(numC); // 25
System.out.println("==============");
final int[] array = {10, 20, 30}; // 地址值不可变
System.out.println(Arrays.toString(array)); // [10, 20, 30]
array[1] = 25;
System.out.println(Arrays.toString(array)); // [10, 25, 30]
权限修饰符
public > protected > (default) > private
同一个类(自己) YES YES YES YES
同一个包(邻居) YES YES YES NO
不同包子类(儿子) YES YES NO NO
不同包非子类(陌生人) YES NO NO NO
注意事项:
1. (default)并不是关键字default,而是什么都不写。
2、只要不是相同的包都需要导包。
内部类
概念:在一类的里面再定义一个类,里面的类就叫做内部类。
内部类的分类:
1、成员内部类
2、局部内部类(包含匿名内部类)
成员内部类的定义格式:
修饰符 class 类名称{
修饰类 class 内部类名称{
//...
}
}
使用 :
1、间接使用:在外部类的成员方法中,创建一个内部类的对象。直观调用外部类对象的外部成员方法即可。
2、直接使用:直接使用内部类对象,公示:
// 外部类.内部类 对象名 = new 外部类().new 内部类();
Outer.Inner obj = new Outer().new Inner();
obj.methodInner();
备注 :
1、外部类和内部类仍然可以继续定义成员变量、成员方法、而且用本类当中的东西,仍然是随便用。
2、内部类如果访问外部类的内容,可以随意。
3、外部类访问内部类的内容,必须有一个内部类的对象才行。
4、编译生成的.class文件名称为“外部类$内部类.class
”
内部类访问外部类的成员变量:
外部类名.this.成员变量名;
成员内部类:定义在外部类内,在方法外
局部内部类:外部类的成员方法内,只有本方法内才有用。(一定要定义局部内部类,然后才能使用。)
成员内部类的权限修饰符:
1、外部类:public
、(default
)
2、成员内部类:public
、protected
、(default
)、privete
3、局部内部类:什么都不能写,而且这并不是(default
)方法。
局部内部类访问所在的方法的局部变量,那么这个变量一定需要是有效的final才行。
因为局部变量和内部累创建的对象生命周期不同。
匿名内部类
接口名称 对象名 = new 接口名称(){
//实现所有抽象方法。
};
解析:
new:创建对象
右侧的接口名称:匿名内部类所实现的接口名。
右侧的{ }:匿名内部类。
public class DemoMain {
public static void main(String[] args) {
// 有对象名叫obj,也有类名称叫MyInterfaceImpl
MyInterface obj = new MyInterfaceImpl();
obj.method();
// 没有对象名称,匿名对象,但是有类名称Impl
new MyInterfaceImpl().method(); // 匿名对象
// MyInterface inter = new MyInterface(); // 错误写法!
// 匿名内部类,没有类名称;但是有对象名称叫做obj2
MyInterface obj2 = new MyInterface() {
@Override
public void method() {
System.out.println("匿名内部类执行!");
}
};
obj2.method();
// 既是匿名对象,也是匿名内部类
new MyInterface() {
@Override
public void method() {
System.out.println("匿名对象+匿名内部类");
}
}.method();
}
}
匿名对象类的好处:省去了单独定义一个实现类的麻烦。
Anonymous匿名内部类
1、匿名内部类的使用前提:必须有继承或者接口实现关系。
2、匿名内部类可以使用接口,也可以使用抽象类,也可以使用普通的类。只要不是final的,就可以。
3、匿名内部类(局部内部类)编译之后因为没有名字,所以产生的字节码文件是“外部类名称$1.class
”。
接口作为成员变量的类型。
接口作为方法的返回值。
public class Body { // 外部类,代表身体
private int num = 10;
public void methodOuter() {
Heart heart = new Heart();
heart.beat();
// System.out.println(age); // 错误
System.out.println(heart.age); // 正确
}
public class Heart { // 内部类,代表心脏
int age = 30;
public void methodInner() {
System.out.println(num);
}
public void beat() {
System.out.println("蹦跶~蹦跶~蹦跶~");
}
}
}
测试类:
// 通过Body间接使用Heart
Body body = new Body(); // 创建了外部类对象
body.methodOuter();
// 直接使用Heart内部类对象
Body.Heart heart = new Body().new Heart();
heart.beat();
heart.methodInner(); // 10