final解析,public、protected、default、private作用域解析

1、final

最终的

  • 修饰类:表示类不可以被继承
  • 修饰方法:表示方法不可被子类覆盖,但是可以重载
  • 修饰变量:表示变量一旦赋值就不可以更改它的值

(1)修饰成员变量

  • 修饰类变量(静态变量):只能在声明该类变量时指定初始值或者静态代码块中指定初始值
  • 修饰成员变量:可以在声明时、普通代码块中、构造方法里指定初始值

(2)修饰局部变量

系统不会为局部变量初始化,在使用前必须指定初始值,也可以直接在声明的时候指定初始值,而无论哪种方法指定初始值,后面都不能更改这个值

public class FinalTest {
	// 在声明时赋值,或者在静态代码块中赋值
	final static int a = 1;
	/**
	static {  // 静态代码块必须在声明的后面
		a = 1;
	}
	*/

	// 在声明时赋值,或者在普通代码块中赋值,或者在构造器中赋值
	final int b = 2;
	// 成员变量不能在静态代码块中复制,因为会先加载静态代码块,再加载成员变量
	/**
	{
		b = 2;
	}
	public FinalTest(int b) {
		this.b = b;
	}
	*/
	public static void main(String[] args) {
		final int localA; // 可以在声明时赋值,也可以后续赋值
		localA = 3; // 但是不允许第二次赋值
		System.out.println(localA);
	}
}

(3)修饰基本数据类型和引用数据类型

  • 修饰基本数据类型:数值一旦初始化就不能更改
  • 修饰引用数据类型:初始化后不能再指向另外一个对象,但是引用的值可以更改
public class FinalReferenceTest {
	public static void main(String[] args) {
		final int[] arr = {1,2,3,4};
		arr[2] = 10; // 合法
		// arr = null; // 非法
		
		final Animal  a1 = new Animal("老虎");
		a1.setName("狮子"); // 合法
		// p = null; // 非法
		// p = new Animal("豹子");// 非法
	}
}

为什么局部内部类和匿名内部类只能访问局部final变量

局部内部类和匿名内部类在编译之后会生成两个class文件,Test.class、Test1.class

public class Test {
	// 局部final变量
	public void test(final int b) {
		final int a =34; // 局部变量
		// 匿名内部类
		new Thread() {
			public void run() {
				System.out.println(a);
				System.out.println(b);
			}
		}.start();
	}
}
public class Test {
	// 成员变量
	private int age = 23;
	// 局部final变量
	public void test(final int b) {
		final int a =34; // 局部变量
		// 局部内部类
		class InClass {
			public void inPrint() {
				System.out.println(a);
				System.out.println(b);
				System.out.println(age); // 可以访问成员变量
			}
		}
		new InClass().inprint();
	}
}

注意:内部类和外部类是处于同一级别的,不会因为方法执行完毕而被销毁

这里就会产生一个问题:那就是当外部类的方法执行完后,局部变量就会销毁,但是内部类还在使用,所以就产生了矛盾,为了解决这个问题,就将局部变量复制一份作为内部类的成员变量,这样即使外部类方法中的局部变量销毁了,内部类依然能使用;匿名内部类也是同样

但是这里又产生了一个新问题,既然是复制的局部变量作为内部类的成员变量,那如果局部变量的值被更改了,而内部类却依然在使用之前复制过来的值,这就会造成数据不一致的问题,那怎么解决呢?

那就是将局部变量设置为final,对它初始化后,不能更改它的值,这样就保证了数据的一致性。

2、public、protected、default、private

2.1、作用域

修饰符同一个类同一个包不同包(子类)不同包(非子类)
private
default
protected
public

private:被private修饰的方法和变量只能在类内部使用
default:不加任何修饰符的方法和变量默认为default,只能在类内部使用或者在同一个包下使用
protected:被protected修饰的方法和变量可以在类内部使用,也可以在子类里面使用(子类与父类之间同包或不同包都行),只是不能在不同包下的非子类使用
public:作用域最广,基本在哪都能用

2.2、测试

包结构:
在这里插入图片描述

类(PDTest):

package p1;

import p2.Father2;

public class PDTest1 {
	public static void main(String[] args) {
		System.out.println("===同一个包下(非子类)====");
		Father f = new Father();
		System.out.println("a: " + f.a);
		System.out.println("b:" + f.b);
		f.printDefault();
		f.printProtected();
		System.out.println("===同一个包下(子类)====");
		Child c = new Child();
		c.pringFather();
		System.out.println("===不同一个包下(非子类)====");
		Father2 f2 = new Father2();
		// System.out.println("a2: " + f2.a2);
		// System.out.println("b2:" + f2.b2);
		// f2.printDefault2();
		// f2.printProtected2();
		// 无论是protected还是default都不可以访问
		System.out.println("无论是protected还是default都不可以访问");
		System.out.println("===不同一个包下(子类)====");
		Child2 c2 = new Child2();
		c2.pringFather2();
	}

}
// 父类
class Father {
	int b;
	protected int a;
	protected void printProtected() {
		System.out.println("Protected: " + a);
	}
	void printDefault() {
		System.out.println("Default: " + b);
	}
}
// 子类
class Child extends Father {
	public void pringFather() {
		super.printDefault();
		super.printProtected();
		System.out.println("super.b:" + super.b);
		System.out.println("super.a:" + super.a);
	}
}
//子类2
class Child2 extends Father2{
	public void pringFather2() {
		// super.printDefault2(); // 不同包下的子类不能使用Default
		super.printProtected2();
		// System.out.println("super.b2:" + super.b2);
		System.out.println("super.a2:" + super.a2);
	}
}

Father2:

package p2;

// 父类2
public class Father2 {
	int b2;
	protected int a2;
	protected void printProtected2() {
		System.out.println("Protected2: " + a2);
	}
	void printDefault2() {
		System.out.println("Default2: " + b2);
	}
}

执行结果:
在这里插入图片描述

在同一个包下,无论是不是子类都可以使用protected和default修饰的方法及变量

在不同包下,非子类对象无论是default还是protected都无法访问,而子类可以访问protected,无法访问default

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值