final关键字和内部类
final常见的四种用法:
1.可以用来修饰一个类
2.可以用来修饰一个方法
3.可以用来修饰一个局部变量
4.可以用来修饰一个成员变量
修饰类和方法
当final关键字用来修饰一个类的时候,格式:
public final class 类名称{
//...
}
含义:当前这个类不能有任何的子类。
其中所有的成员方法都无法覆盖重写。
当final关键字用来修饰一个方法的时候,格式
修饰符 final 返回值类型 方法名称(参数列表){
//方法体
}
对于类、方法来说,abstract关键字和final关键字不能同时使用,因为矛盾。抽象方法需要重写,final关键字不被能重写。
public final class Fu{
public void method(){
System.out.println("方法1");
}
/*public abstract final void method(){
System.out.println("抽象方法需要被重写,final关键字不能被重写");
}//错误写法*/
}
public class Zi/* extends Fu*/{
public void method(){
System.out.println("方法2");
}
}
修饰成员变量和局部变量
对于成员变量来说,如果使用final关键字修饰,那么这个变量也照样是不可变
1.由于成员变量具有默认值,一旦用了final关键字之后,必须手动赋值。
2.对于final的成员变量,要么直接赋值,要么通过构造方法赋值。二者选其一。
3.必须保证类当中所有重载的构造方法,最终会对final的成员变量进行赋值。
成员变量
public class Person {
private final String name;
/*private final String name = “方”;//手动赋值*/
public Person() {
name = "关";//通过构造方法赋值
}
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
/*public void setName(String name) {
this.name = name;//使用final修饰后,无法改变,setter方法用不上
}*/
}
局部变量
public class Final {
public static void main(String[] args) {
int num1 = 10;
System.out.println(num1);
num1 = 20 ;
System.out.println(num1);
//一旦使用final用来修饰局部变量,那么这个变量就不能更改,一次赋值,终生不变
final int num2 = 200;
//对基本类型来说,不可变说的是变量当中的数据不可改变
//对引用类型来说,不可变说的是变量当中的地址值不可改变
Student stu1 = new Student("放");
System.out.println(stu1);
stu1 = new Student("稳");
System.out.println(stu1);
final Student stu2 = new Student("wen");
//stu2 = new Student("方文辉");//错误,final引用类型 地址值不能改变
System.out.println(stu2.getName());
}
}
内部类
内部类
分类:
1.成员内部类
2.局部内部类(包含匿名内部类)
成员内部类的定义格式
修饰符 class 类名称{
修饰符 class 类名称{
//....
}
//....
}
注意:内用外,随意访问:外用内,需要内部类对象。
===================================
如何使用成员内部类?有两种方式:
1.间接方式:在外部类的方法当中,使用内部类;然后main只是调用外部类的方法。
2.直接方式,公式:
类名称 对象名 = new 类名称();
外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();
成员内部类
public class Body {//外部类
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public class Heart{//成员内部类
public void beat(){
//内部类方法
System.out.println("心脏跳动");
System.out.println("我叫 " + name);
}
}
public void methodBody(){
System.out.println("外部类方法");
new Heart().beat();
}
}
//如果出现了重名现象,那么格式是:外部类名称.this.外部类成员变量名
public class Outer {
int num = 10 ;
public class Inners{
int num = 20 ;
public void methodInner(){
int num = 30 ;
System.out.println(num);
System.out.println(this.num);
Outer outer = new Outer();
System.out.println(outer.num);
System.out.println(new Outer().num);
System.out.println(Outer.this.num);
}
}
}
public class OuterClass {
public static void main(String[] args) {
//借助外部类方法
Body body = new Body();
body.methodBody();
//按照公式
Body.Heart heart = new Body().new Heart();
heart.beat();
Outer.Inners inner = new Outer().new Inners();
inner.methodInner();
}
}
局部内部类
如果一个类是定义在一个方法内部的,那么这就是一个局部内部类。
“局部”:只有当前所属的方法才能使用它,出了这个方法外面就不能用了。
定义格式:
修饰符 class 外部类名称{
修饰符 返回值类型 外部类方法名称(参数列表){
class 局部内部类名称{
//......
}
}
}
public class Inner {
public void methodOuter(){
class Inner1{
int num = 10;
public void methodInner(){
System.out.println(num);
}
}
Inner1 inner1 = new Inner1();
inner1.methodInner();
}
}
匿名内部类
如果接口的实现类(或者是父类的子类)只需要使用唯一的一次
那么这种情况下就可以省略掉该类的定义,而改为使用【匿名内部类】
匿名内部类的定义格式:
接口名称 对象名 = new 接口名称(){
//覆盖重写接口中所有抽象方法
};
另外还要注意几点问题:
1.匿名内部类在创建对象的时候,只能使用唯一一次。如果希望多次创建对象,而且内容一样的话,
那么就必须使用单独定义的实现类。
2.匿名对象,在【调用方法】的时候,只能调用唯一一次。
如果希望同一个对象,调用多次方法,那么必须给对象起个名字。
3.匿名内部类是省略了【实现类/子类名称】,但是匿名对象是省略了【对象名称】
public interface MyInterFace {
void method();
}
public class MyInterfaceImp implements MyInterFace{
@Override
public void method() {
System.out.println("覆盖重写");
}
}
public class ImpMyInterfaceImp {
public static void main(String[] args) {
/*MyInterfaceImp myInterfaceImp = new MyInterfaceImp();
myInterfaceImp.method();*/
MyInterFace interFace = new MyInterFace() {
@Override
public void method() {
System.out.println("匿名内部类重写方法");
}
};
interFace.method();//匿名内部类重写方法
MyInterfaceImp myInterfaceImp = new MyInterfaceImp(){
public void method(){
System.out.println("这里重写了");
}
};
myInterfaceImp.method();//这里重写了
new MyInterFace(){
@Override
public void method() {
System.out.println("匿名对象匿名内部类");
}
}.method();//匿名对象匿名内部类
}
}