2021-10-22 迈向程序猿的第十二步

目录

一.Static

1.1 静态属性

1.2 静态方法

1.3 动态代码块与类加载

二.final


一.Static

java中的五大存储区域:
栈、堆、方法区、寄存器区、本地方法区
寄存器区:主要是线程的存储区域
本地防区:第三方语言的存储区域,例如:c/c++

重点分析三大区域:堆,栈,方法区
栈:存局部变量  (引用对象,基本变量)
堆:new对象,成员属性
方法区:class文件,静态区(static修饰),常量池(字符串常量)-往往方法区的东西只有一份

1.1 静态属性

①成员属性

class MyClass{
	int a;  //成员属性
}


public class Test1 {
	public static void main(String[] args) {
		MyClass obj1 = new MyClass();
		MyClass obj2 = new MyClass();
		
		obj1.a = 3;
		obj2.a = 5;
		
		System.out.println(obj1.a+"---"+obj2.a);
	}
}

 

②静态属性

//实例属性 VS 静态属性
//实例属性: 在堆区,属于对象,通过对象调用;每个对象独有的一份
//静态属性: 在方法区,属于类,推荐使用类名调用;所有对象共享同一份

class MyC{
	static int a;
}
public class Test2 {
	public static void main(String[] args) {
		MyC obj1 = new MyC();
		MyC obj2 = new MyC();
		
		//The static field MyC.a should be accessed in a static way
		obj1.a = 3;  //MyC.a = 3; 静态属性属于类,推荐通过类名调静态属性
		obj2.a = 5;
		
		System.out.println(obj1.a+"---"+obj2.a);
	}
}

1.2 静态方法

//问题:在静态方法中,能否使用成员属性;--不能  
      //在成员方法中能否使用静态属性?--能  为什么?

//思考: 函数入口为何要这么设计?    public  static void main()
//public:公开权限,使得外部jvm有权限调用
//static:优先加载,无需new对象,提高性能
//void:  无需反馈结果到jvm 

class MyClass{
	static int a;   //静态属性
	int  b;         //成员属性
	
	//静态方法中不能使用this与super关键字--加载时机问题
	//静态方法可以继承,但不能重写
	public static void test() {  //静态方法
		System.out.println("测试的方法...");
		//加载时机问题,静态区在类加载时就进行加载了,这时还不知道对象属性; 静态区优先对象加载
		//System.out.println(b); 
	}
	
	public void print() {
		System.out.println(a);
	}
}

class Son extends MyClass{
	/*@Override   
	public static void test() {  //静态方法,不能重写
	}*/
}

public class Test1 {
	public static void main(String[] args) {
		//之前方法调用,因为是调当前类的方法,所有省略了类名的调用
		System.out.println(add(1,2));  //调当前类的方法  等价Test1.add(1,2);
		
		//The static method add(int, int) from the type Test1 should be accessed in a static way
		System.out.println(new Test1().add(3, 5)); //可以通过对象调静态方法,但是不推荐
		
		//调用系统提供的静态方法
		int[] a = {1,2,3};
		System.out.println(Arrays.toString(a)); //调其他类的方法: 类名.方法
		
		MyClass.test();  //调用自定义类的静态方法
		
		//new Son().test();  //静态方法具有继承性
	}

	//静态方法:属于类,推荐使用类名调用
	public static int add(int a, int b) {
		return a+b;
	}
}

1.3 动态代码块与类加载

①动态代码块

//动态代码块: 就是类中的一块区域,只要在类中加入{},就是一个代码块;
//通过实例化对象可以触发到动态代码块
//执行流程:
//成员属性>动态代码块>构造方法
//作用: 给属性赋予初始值

//类加载过程:
//jvm根据classpath查找class文件,并将class文件中的所有信息(包名,类名,对象,属性,方法等)加载到内存中
//需要在入口main中触发执行类加载

class MyClass{
	String a = "成员属性";
	static String b = "静态属性";
	
	{
		System.out.println(a);
		System.out.println("动态代码块");
	}
	
	public MyClass() {
		System.out.println("构造方法");
	}
	
	public static void show() {
		System.out.println("调用静态方法");
	}
}

class Son extends MyClass{
	
}
public class Test1 {
	public static void main(String[] args) throws ClassNotFoundException {
		//new MyClass();  //实例化对象触发
		//new Son();        //实例化子类对象
		//System.out.println(MyClass.b);  //静态属性触发类加载
		//MyClass.show();   //使用静态方法触发类加载
		Class.forName("com.qf.c_statickuai.MyClass");  //加入全限定名,触发类加载-反射后面学
	}
}

②静态代码块

//静态代码块的执行:
//先执行静态属性>静态代码块(通过反射触发)
class MyC{
	static String a = "静态属性";
	//静态代码块
	static {
		System.out.println(a);
		System.out.println("静态代码块");
	}
	
}

public class Test2 {
	public static void main(String[] args) throws ClassNotFoundException {
		Class.forName("com.qf.c_statickuai.MyC");
	}
}

③动态代码块与静态代码块

//对象的执行过程(动态代码块+静态代码块):
//规则: 先静态,后动态     静态属性->静态代码块->成员属性->动态代码块->构造方法
//再new一个对象: 再执行一次,成员属性->动态代码块->构造方法
//结论:static与对象无关,静态代码块只加载一次,优先于非静态的执行
class Super{
	static String a = "父类静态属性";
	String  b = "父类成员属性";
	static {
		System.out.println(a);
		System.out.println("父类静态代码块");
	}
	
	{
		System.out.println(b);
		System.out.println("父类动态代码块");
	}
	
	public Super() {
		System.out.println("构造方法");
	}
}

public class Test1 {
	public static void main(String[] args) {
		new Super();  //实例化当前类的构造方法    先静态,后动态
		System.out.println("===============");
		new Super();  //再new一个对象
	}
}

④子类的实例化过程

//案例:子类继承Super类,观察子类实例化过程
//规则: 先父类,再子类,先静态,后动态

//执行流程:父类静态属性>父类静态代码块>子类静态属性>子类静态代码块>父类成员属性>父类动态代码块
      // 父类构造方法>子类成员属性>子类动态代码块>子类构造方法
class Son extends Super{
	static String a = "子类静态属性";
	String b = "子类成员属性";
	{
		System.out.println(b);
		System.out.println("子类动态代码块");
	}
	
	static {
		System.out.println(a);
		System.out.println("子类静态代码块");
	}
	
	public Son() {
		System.out.println("子类构造方法");
	}
}

public class Test2 {
	public static void main(String[] args) {
		 new Son();
	}
}

二.final

final:表示最终的,可以修饰类,方法,属性
修饰类:最终类(太监类),被final修饰的类不能有子类
修饰方法: 该方法不能被重写
修饰属性: 变量变为了常量,往往在静态属性中与static配合使用(状态值)-静态常量

//final修饰类,该类不能有子类
/*final*/ class Super{
	//静态常量必须初始化时要赋值
	//静态常量赋值时机:1.初始时赋值   2.静态代码块
	public final static int COUNT=1;  //状态值往往是不能被改变的,+final修饰则变为了常量
	/*static {
		COUNT = 2;
	}*/

	//成员常量必须初始化时要赋值
	//成员常量赋值时机: 1. 初始时赋值   2.动态代码块   3.构造方法
	public final int d=1;
	/*{
		d = 3;
	}*/
	
	/*public Super() {
		d = 5;
	}*/
	
	
	
	//final修饰方法,该方法不能被重写
	public /*final*/ void test(){
		
	}
}

//The type Son cannot subclass the final class Super
class Son extends Super{
	int b;
	@Override
	//Cannot override the final method from Super
	public void test(){
		
	}
}

public class Test1 {
	public static void main(String[] args) {
		//Super.COUNT = 5;  //The final field Super.COUNT cannot be assigned
		
		//基本类型的局部变量中的final修饰: 该变量值不能改变
		final int a = 3;
		//a = 5;  不能改变
		
		//引用类型的局部变量中加final修饰: 该变量地址不能改变,与属性值无关
		final Son son = new Son();
		//son.b = 6;
		//son = new Son();  //地址不能改变
		
		//数组也是引用类型,修饰数组后,地址不能变,里面的元素值可以变
		final int[] c = {1,2,3};
		//c = new int[]{4,5};  //地址不能改变
		c[0] = 6;
		
	}
}

(=1=,距离10.24程序猿节还有两天,今天小白玩转盘活动,成功收获一个纪念杯!在这也提前祝大伙程序员节快乐!)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值