java中的静态相关知识、内存存储分析

目录

 

 

 

 

一、JAVA的内存分析

1.内存概述:

2.案例分析

二、静态-修饰属性

1.静态属性和成员属性

2.场景-统计全局资源3

3.场景-状态值应用

三、静态-修饰方法

1.特点

2.工具类

四、静态-修饰代码块

1.动态代码块

2.类加载

3.静态代码块

4.实例化过程

五、final的使用

1.修饰类和方法

2.修饰变量

六、总结

 


 

一、JAVA的内存分析

1.内存概述:

java的内存存储总共分为5大区域堆、栈、方法区、本地方法区、寄存器区

 

其中本地方法区(存第三方语言-C/C++)和寄存器区(多线程资源)不用区分析,没法跟踪这两个区域

 

重点分析:堆,栈,方法区

 

堆:存new对象,成员属性,常量池(放字符串常量,之前方法区,现在放堆区-性能考虑,但沿用了方法区特点)

 

栈:存局部变量

 

方法区:class资源,static资源; 特点:优先于对象的加载,且相同资源只维护一份

接下来,使用简单的面向对象案例,说明内存的执行过程

2.案例分析

//案例:小明在打游戏
//分析:类-Person,对象:new   属性-姓名,方法:打游戏
//内存分析流程:
//1.类加载Test1.class与Person.class---方法区
//2.new对象开辟空间-------堆区
//3.将地址赋值给引用变量person-------栈区
class Person{
    String name;
    public void play() {
        System.out.println(name+"正在打游戏");
    }
}
public class Test1 {
    public static void main(String[] args) {
        Person person = new Person();
        person.name = "小明";
        person.play();
    }
}

二、静态-修饰属性

1.静态属性和成员属性

//案例:女朋友帮忙洗衣服
//成员变量结论:实例化多个对象,每个对象都有独立的成员属性
//静态变量结论:实例化多个对象,共享同一份静态变量
//成员变量  VS  静态变量
//1.存储位置   静态变量-方法区                成员变量-堆
//2.所属资源   静态变量-类                    成员变量-对象
//3.执行顺序   静态变量优先于成员变量进行加载;在类加载时,就已经加载了静态资源
//4.调用方式   静态变量-推荐用类调        成员变量-对象调

class Girl{
    //String name;  //成员变量
    static String name;  //静态变量
    
    public void wash() {
        System.out.println("女朋友"+name+"正在帮忙洗衣服");
    }
}
public class Test1 {
    public static void main(String[] args) {
        Girl lyf = new Girl();
        Girl.name="刘亦菲";   //lyf.name = "刘亦菲";  
        
        Girl fj = new Girl();
        Girl.name  = "凤姐";
        
        lyf.wash();  //凤姐
        fj.wash();   //凤姐
        
        //说明:在面向对象中,直接使用静态变量场景不多;但有些场景下,还是用得较多
        //例如:统计全局资源及作为状态值(静态常量)的使用
    }
}

2.场景-统计全局资源3

//案例:统计某个对象被new了多少次
//分析:实例化对象后,使用构造方法来记录次数
class A{
	//int count;   //初始为0  //成员变量:每个对象都是独立的一份
	static int count;  //静态变量:所有对象共享同一份
	public A() {
		count++;  //每次new了之后,然后+1
	}
}
public class Test2 {
	public static void main(String[] args) {
		new A();
		new A();
		new A();
		System.out.println("次数:"+A.count);
	}
}

3.场景-状态值应用

//状态值---静态常量  static+final
//final最终的,修饰变量,变为常量;所存的数值不可改变
//往往这种静态常量可以用于状态值,也就是系统给定值(也可自定义),用于判断,不要改变它
//好处:可读性很强,维护性很强

案例:

//案例:200响应码-成功    404-找不到访问页面   500-服务器报错
//模拟代码实现:
public class Test3 {
	public static final  int HTTP_OK = 200;  //状态值
	public static final int HTTP_ERR = 404;
	public static final int SERVER_ERR = 500;
	
	public static void main(String[] args) {
		int repcode = getResponseCode();
		//HTTP_OK = 400;  final修饰的不能更改
		switch (repcode) {
		case HTTP_OK:
			System.out.println("返回成功页面!");
			break;
		case HTTP_ERR:
			System.out.println("访问页面未找到!");
			break;
		case SERVER_ERR:
			System.out.println("服务器出现异常");
			break;
		default:
			System.out.println("错误的响应码");
			break;
		}
	}
	private static int getResponseCode() {
		//执行了很多后端操作
		return HTTP_OK;
	}
}

 

三、静态-修饰方法

1.特点

修饰方法时,在静态方法中不能使用成员变量

案例:

class A{
	String name;  //成员变量
	static int age;
	public void eat() {  //成员方法
		System.out.println(name+"正在吃");
		System.out.println(age); //在成员方法中,可以使用静态变量
	}
	public static void test() {  //静态方法
		//在静态方法中不能使用成员变量,因为加载时机问题-static优先加载,不认识成员
		//System.out.println(name); 
		//System.out.println(this.name);  //静态方法中不能使用this或super关键字
		//静态方法可以继承,但不能重写
	}
}
class B extends A{
	/*@Override   //静态方法不能重写
	public static void test() {
	}*/
}
public class Test1 {
	public static void main(String[] args) {
		B.test();  //静态方法具有继承性
	}
}

 

 

2.工具类

//工具类的应用---通过类名直接调静态方法
//好处:不需要通过new对象进行调用;如果需要多次调用,可节约内存
//例如系统提供的:System,Arrays都是工具类的用法
//System.arraycopy;  Arrays.sort  Array.copyOf  Arrays.toString

案例:

class MyArrays{
	public static void sort(int[] a) {
		//冒泡排序:
		for(int i=0;i<a.length-1;i++) {
			for(int j=0;j<a.length-1-i;j++) {
				if(a[j]>a[j+1]) {
					int t = a[j];
					a[j] = a[j+1];
					a[j+1]= t;
				}
			}
		}
	}
}
public class Test2 {
	public static void main(String[] args) {
		int[] a = {2,6,4,8,3};
		MyArrays.sort(a);  //自定义工具类
		System.out.println(Arrays.toString(a));
	}
}

 

四、静态-修饰代码块

1.动态代码块

在类中写入{},就是一个动态代码块,只要实例化一次对象,即可触发一次代码块

执行时机:属性赋值>动态代码块>构造方法

作用:可用于给属性赋值

 

案例:

//动态代码块应用:
class A{
	String name = "成员属性";
	public A() {  //构造方法
		System.out.println("构造方法");
	}
	//动态代码块
	{
		System.out.println(name);
		System.out.println("动态代码块");
	}
}
public class Test1 {
	public static void main(String[] args) {
		new A();
	}
}

 

2.类加载

//类加载机制:
//JVM首次使用某个类,通过classpath找到.class文件,并将类资源加载到内存中
//这些类资源包括:包名,类名,属性,方法,对象...
//类加载的触发时机:run 配置--verbose
//1.实例化对象
//2.实例化子类对象
//3.静态属性触发
//4.静态方法触发
//5.使用反射触发

案例:

class B{
	static String name="静态属性";
	public static void show() {
		System.out.println("静态方法触发");
	}
}
class C extends B{	
}
public class Test2 {
	public static void main(String[] args) throws ClassNotFoundException {
		//new B();  //类加载只有一份;与实例化多次对象无关
		//new B();
		//new C();   //实例化子类对象
		//System.out.println(B.name);  //静态属性
		//B.show();    //静态方法
		Class.forName("com.qf.d_block.B");   //全限定名   反射应用(后面学)
	}
}

 

3.静态代码块

//静态代码块: static{}
//执行顺序:静态属性>静态代码块
//作用:用于给静态属性赋值

class D{
	static String name="静态属性";
	static {
		System.out.println(name);
		System.out.println("静态代码块");
	}
}
public class Test3 {
	public static void main(String[] args) {
		new D();
	}
}

 

4.实例化过程

//将静态代码块与动态代码块综合应用:
class Super{
	String name = "成员属性";
	public Super() {  //构造方法
		System.out.println("构造方法");
	}
	//动态代码块
	{
		System.out.println(name);
		System.out.println("动态代码块");
	}
	
	static String name2="静态属性";
	static {
		System.out.println(name2);
		System.out.println("静态代码块");
	}
}
public class Test1 {
	public static void main(String[] args) {
		new Super(); //静态属性>静态代码块>成员属性>动态代码块>构造方法
		System.out.println("---------------");
		new Super();  //成员属性>动态代码块>构造方法   静态的只加载一次
	}
}

 

实例化子类对象的执行过程:

    //静态属性>静态代码块>子类静态属性>子类静态代码块>成员属性>动态代码块>构造方法
        //>子类成员属性>子类动态代码块>子类构造方法
        //规则:先静态后动态,先父类后子类

 

class Son extends Super{
	String name = "子类成员属性";
	public Son() {  //构造方法
		System.out.println("子类构造方法");
	}
	//动态代码块
	{
		System.out.println(name);
		System.out.println("子类动态代码块");
	}
	
	static String name2="子类静态属性";
	static {
		System.out.println(name2);
		System.out.println("子类静态代码块");
	}
}
public class Test2 {
	public static void main(String[] args) {
			new Son();   //实例化子类对象的过程
	}
}

 

 

五、final的使用

final表示最终的,不可更改的;

应用:可以修饰类,修饰属性,修饰变量

修饰类: 最终类,该类不能有子类----太监类

修饰方法:最终方法,该方法不能被重写

修饰变量:最终变量,变为了常量

1.修饰类和方法

案例:

/*final*/ class Animal{ //最终类-不能有子类 ; 例如String
	public /*final*/  void eat() { //最终方法,子类不能重写
		
	}
}
class Dog extends Animal{ //The type Dog cannot subclass the final class Animal
	@Override
	public void eat() { //Cannot override the final method from Animal
		
	}
}
public class Test1 {
	public static void main(String[] args) {
		
	}
}

 

2.修饰变量

final修饰变量,有多种变量,成员变量,静态变量,局部变量(其中局部变量包含了基本和引用变量)

案例:

//成员属性+final赋值:1.直接赋值    2.动态代码块  3.构造方法
//静态属性+final赋值: 1.直接赋值   2.静态代码块
class Pig{
	//The blank final field name may not have been initialized
	final String name/*="张三"*/;  //成员变量会变成常量,需要初始赋值
	/*{
		name = "张三丰";
	}*/
	public Pig() {
		name = "张三疯";
	}
	static final String sex/*="男"*/;  //状态值的使用--常用
	static {
		sex = "女";
	}
	int  count = 5;
}
public class Test2 {
	public static void main(String[] args) {
		final int a = 3;
		//a = 5;  //final修饰基本类型变量,值不能改变
		
		//final修饰应用类型变量:数组、对象
		//1.final修饰数组
		final int[] as = {1,3,5}; //new 空间的简写  
		as[0] = 66;  //值可变
		//as = new int[] {2,4};  //final修饰引用变量, 地址不可变
		
		//2.final修饰对象
		final Pig pig = new Pig();
		//pig = new Pig();  //地址不可变
		pig.count = 3;  //里面的属性值可改变
	}
}

 

六、总结

1.内存分析
内存存储的5大区域;重点分析:堆,栈,方法区(重点)
通过案例说明了内存的执行流程
2.静态属性
静态属性与成员属性的区别(重点)
应用场景:统计全局资源; 状态值的使用(重点)
3.静态方法
静态方法的特点;应用场景:作为工具类使用(重点)
4.静态代码块
动态代码块的执行与作用;类加载的过程与触发机制
静态代码块的执行(重点)
实例化过程:实例化当前对象与子类对象的静态和动态代码块综合案例
5.final的使用
修饰类,修饰方法,修饰变量(修饰静态变量用得多-静态常量)

 

 

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值