一、final关键字
为什么要使用 final 关键字?
通过继承我们知道,子类可以重写父类的成员变量和方法。final 关键字可以用于修饰父类,父类成员变量和方法,使其内容不可以被更改。
1.被修饰的类,不能被继承。但是其成员变量和方法如果未被final修饰,仍然可以被修改。
//final修饰类 final class Finally1 { private int a = 1; public int getA(){ return this.a; } public int setA(int a){ this.a = a; return this.a; } } class Finally2 extends Finally1{} 无法被继承 public class TestFinally{ public static void main(String[] args){ final Finally1 f1 = new Finally1(); System.out.println(f1.getA()); System.out.println(f1.setA(2));//修改a = 2; System.out.println(f1.getA()); } }
Finally2 无法继承 Finally1。
2.被修饰的方法,不能被重写。
1 class Finally1 { 2 private int a = 1; 3 public final int getA(){ 4 return this.a; 5 } 6 public int setA(int a){ 7 this.a = a; 8 return this.a; 9 } 10 } 11 class Finally2 extends Finally1{ 12 public int getA(){ //编译无法通过 13 System.out.println("getA无法被重写"); 14 } 15 16 }
上面代码中,Finally2 子类继承 Finally1 父类,并重写了getA()方法,导致编译无法通过。
3.被修饰的变量(无论是成员变量还是局部变量),只能赋值一次,不能被重新赋值。
//final修饰变量 final class Finally1 { final private int a = 1; public int getA(){ return this.a; } public int setA(int a){ this.a = a; //a的值无法被修改,这里会报错 return this.a; } }
普通类型和引用数据类型都符合上面的规则。但是值得注意的是,引用数据类型虽然不能被修改(内存地址),但是对象的局部变量仍然可以被修改。
//final修饰 引用数据类型变量 interface Finally1{ public default void method(int a){ int b = a; System.out.println(b); } } class Finally2 implements Finally1{ //实现finally1接口 } public class TestFinally { public static void main(String[] args){ final Finally1 f2 = new Finally2(); f2 = new Finally2(); //f2不可以被重新赋值新的对象 f2.method(1); //引用数据类型的局部变量仍然可以被修改 } }
二、权限修饰符
Java中提供了四种访问权限修饰符:
- public:公共权限。表示全部都可以访问。
- protected:受保护的权限。不同包中的无关类无法访问。
- default:默认权限(不写时默认使用default)。不同包中的子类和无关类无法访问。
- private:私有权限。表示只能在当前类中访问。
建议(酌情考虑):
- 成员变量使用 private,隐藏细节。
- 构造方法使用 public,方便创建对象。
- 成员方法使用public, 方便方法调用。
三、内部类
一个类中包含另一个类,后者位于前者类中方法外,所以被称为内部类。
- 内部类可以直接访问外部类的成员,包括私有成员。
- 外部类要访问内部类成员,必须建立内部对象。
class Person { private int a = 1; class Heart{ public void println(){ System.out.println(a); //内部类访问外部类私有成员 } } } public class Test{ public static void main(String[] args){ //创建外部类对象 Person p = new Person(); //创建内部类对象 Person.Heart h = p.new Heart(); //调用内部类方法 必须创建内部类对象 h.println(); } }
关于匿名内部类:其实是内部类的简化写法。它的本质是一个带具体实现的匿名子类对象。匿名内部类要求必须继承一个父类或者实现一个父接口。
class Person { private int a = 1; public void println(){ System.out.println(a); //内部类访问外部类私有成员 } } public class Test{ public static void main(String[] args){ method(new Person(){ public void println(){ System.out.println("我是匿名内部类的成员方法"); } });//匿名内部类 } public static void method(Person p){ p.println(); } }
温馨提示
- 如果您对本文有疑问,请在评论部分留言,我会在最短时间回复。
- 如果本文帮助了您,也请评论关注,作为对我的一份鼓励。
- 如果您感觉我写的有问题,也请批评指正,我会尽量修改。