关键字

final

用法:

修饰一个类

public final class 类名称 {
    //...
}

含义:当前这个类不能有任何的子类(太监类),一定有父类。
因此,修饰的类,其中所有的成员方法都无法覆盖重写(无子类),但可以自身覆盖重写父类的成员方法。

修饰一个方法

修饰符 final 返回值类型 方法名(参数列表) {
    //方法体
}

含义:被final修饰的方法为最终方法不能再被覆盖重写

对于类和方法来说,abstract和final关键字不能同时使用

修饰一个局部变量

final 数据类型 变量名 = 值;
or
final 数据类型 变量名;
变量名 = 值;        //赋值,只要保证有唯一一次赋值即可

含义:被final修饰的变量值,不允许更改,一次赋值,终生不变,并且不允许对已经定义的变量名,改变其值

int num1 = 10;
final num1 = 12;   //Error!!!
不可变
对于基本数据类型,变量中的数据不可变
对于引用数据类型,变量中的地址值不可变

修饰一个成员变量

直接赋值:

构造方法赋值:
    如Person类
private final 数据类型 成员变量名

public Person() {
    成员变量名 = .... ; //此处进行赋值
}
    再去掉下面这个方法
public void setName() {
    ...
}

注意:

1.由于成员变量会自带默认值,null或者0,也属于赋值,所以用了final后必须手动赋值,就不会再给默认值了。
2.对于final的成员变量,要么直接赋值,要么通过构造方法赋值(用了直接赋值,就不要用构造; 二者选一
3.必须保证类当中所有重载的构造方法,都最终会对final的成员变量进行赋值。

四种权限修饰符

public > protected > (default) > private
同一个类( 我自己) YES YES YES YES
同一个包 (我邻居) YES YES YES NO
不同包子类(我儿子) YES YES NO NO
不同包非子类(陌生人) YES NO NO NO

注意事项:
(default)是指不写

定义一个类时,权限修饰符规则:

1.外部类:public/(default)
2.成员内部类:public/protected/(default)/private
3.局部内部类:什么都不能写


内部类

如果一个事物的内部包含另一个事物,那么这就是一个类内部包含另一个类。
例如:身体和心脏,汽车和发动机...

分类:

1.成员内部类

定义格式:

修饰符 class 外部类名称 {
    修饰符 class 内部类名称 {
        //...
    }
    //...
}

内部类使用外部:内用外,可以随意访问
外部类使用内部:外用内,需要内部类对象
.calss文件为:Body.class(外部类)、Body$Heart.class(外部$内部)

使用:

1、间接方式:在外部类的方法中,使用内部类,然后main只是调用外部类的方法。
2、直接方式:外部类.内部类:(Body.Heart)
外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();
Body.Heart obj = new Body().new Heart();

重名现象:外部类名称.this.外部类成员变量名

public class Outer {
    int num = 10;    //外部类成员变量
    
    public class Inner {
        int num = 20;      //内部类成员变量
        
        public void methodInner() {
            int num = 30;        //内部类方法的局部变量
           
            System.out.println(num);   //局部变量,就近原则
            System.out.println(this.num);  //内部类成员变量
            System.out.println(Outer.this.num);  //外部类成员变量

        }
    }
}
若直接
Outer.Inner hh = new Outer().new Inner();

hh.num 是输出20,输出内部类的成员变量

2.局部内部类(包含匿名内部类)

一个类定义在一个方法内部
“局部”:只有当前所属的方法才能使用它,出了这个方法外面就不能用了

格式:
修饰符 class 外部类名称 {

修饰符 返回值类型 外部类方法名称(参数列表) {
    class 局部内部类名称 {
        //...
    }
}

}

访问方法:

public class Outer {

    public void methodOuter() {
        class Part {
            int num = 10;

            public void methodInner() {
                System.out.println(num);
            }
        }
        
        //在这里定义新对象,将访问变量、方法等功能放在这。
        Part inner = new Part();

        inner.methodInner();
    }
}

//主函数
public class Demo04Main {
    public static void main(String[] args) {
        //定义新对象
        Outer obj = new Outer();
        //调用类中的方法
        obj.methodOuter();

    }

}

局部内部类,如果希望访问所在方法的局部变量,这个局部变量必须是【有效final】的。
原因:
1.new出来的对象在堆(heap)内存当中。
2.局部变量跟着方法走,在堆(stack)内存当中。
3.方法运行结束,立刻出栈,局部变量就会立刻消失
4.但是new出来的对象会在堆当中持续存在,直到垃圾回收为止。
所以,类new出来的对象比方法存活久,如果想调用局部变量,可能会消失,相当于是复制成一个常量。

public class MyOuter {
    public void methodOuter() {
        int num = 10;    //所在方法的局部变量

        class MyInner {
            public void methodInner() {
                num = 20; //错误,必须是final的,所以不可以改变
                System.out.println(num);
            }
        }
    }
}

匿名内部类!!!

如果接口的实现类(或者是父类的子类)只需要使用唯一的一次
那么这种情况就可以省略该类的定义,而改为使用【匿名内部类】

格式:

接口名称 对象名 = new 接口名称() {
    //覆盖重写所有抽象方法
};  

有点类似,把实现类写在了主方法内
原过程是定义一个实现类,并在实现类中覆盖重写方法,再new一遍使用;
这是在主方法中就new了,并把原抽象方法在这里覆盖重写,可以少定义一个文件

public class Demo05MyMain {

    public static void main(String[] args) {
        MyInterface obj = new MyInterfaceImpl();
        obj.methodAbs();

        MyInterface hhh = new MyInterface() {
            //覆盖重写所有抽象方法
            @Override
            public void methodAbs() {
                //覆盖重写
            }
        };
    }
}

对格式“new 接口名称() {...}”解析
1.new代表创建对象的动作
2.接口名称就是匿名内部类需要实现哪个接口
3.{...}这才是匿名内部类的内容

注意事项:
1.匿名内部类,在创建对象的时候,只能使用唯一的一次,如果希望多次创建对象,并且内容一样,就必须使用单独定义的实现类了。
2.匿名对象,在【调用方法】的时候只能调用唯一一次。
如果希望同一个对象,调用多次方法,那么必须给对象起个名字。
3.匿名内部类是省略了【实现类/子类名称】,但匿名对象是省略了【对象名称】!!!

        //既是匿名内部类,也是匿名对象
        new MyInterface() {
            @Override
            public void methodAbs() {

            }
            
            @Override
            public void methodAbs2() {

            }
        }.methodAbs(); //通过这种方式访问其中变量与方法
        
//因为匿名对象无法调用第二次方法,所以需要再创建一个匿名内部类的匿名对象。
            new MyInterface() {
            @Override
            public void methodAbs() {

            }
            
            @Override
            public void methodAbs2() {

            }
        }.methodAbs2(); //这样才能调用另一个方法

接口作为成员变量类型
!!!
1.接口再用实现类
2.主方法中用匿名内部类
3.同时使用匿名内部类和匿名对象

//Skill为接口,hero为Hero类定义的对象, void use()是接口的抽象方法
        hero.setSkill(new Skill() {

            @Override
            public void use() {
                
            }
        });

类作为成员变量类型

接口作为方法的参数和返回值

import java.util.ArrayList;
import java.util.List;

    public static void main(String[] args) {
    //定义一个ArrayList
        //ArrayList<String> list = new ArrayList<>();
        
        //多态写法,左边是接口名称,右边是实现类名称
        List<String> list2 = new ArrayList<>();

        //用一个同类型的来接收
        List<String> result = addNames(list2);
    }
    

    public static List<String> addNames(List<String> list) {
        list.add("132");
        list.add("12564");
        list.add("78");

        return list;

    }

  
        

        

java.util.list正是ArrayList所实现的接口


waikiki
4 声望2 粉丝