关键字
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所实现的接口
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。