DaiXT:static的用法浅析

一、static简介

  • 在Java中内存分为栈内存和堆内存,其中栈内存用来存放一些基本类型的变量、数组和对象的引用,堆内存主要存放一些对象。在JVM(虚拟机)加载一个类的时候,若该类中存在static修饰的成员变量、成员方法,则会为这些成员方法在固定的位置开辟一个固定大小的内存区域(即类被加载时,JVM可以根据类名在运行时数据区的方法区内找到它们)。

二、static如何使用

  • static可以修饰成员变量、成员方法、代码块、类。当修饰对象为成员变量或者成员方法的时候可以通过类名调用。

1、static变量

  • 当变量被static所修饰时,称该变量为静态变量,反之为实例变量。

区别如下:

  • 静态变量在类加载时被完全初始化,它在内存中是唯一的,JVM仅为它分配一次内存。实例变量随着实例的创建而产生,与该实例同生共死。

采用静态变量的目的如下:

  • 作为共享变量
  • 减少对象创建的次数
  • 保留唯一的副本

2、static方法

  • 静态方法不依赖于任何对象访问,不存在super或this的调用。静态方法中访问非静态变量或方法,需要创建访问的对象。
  • 静态成员变量的初始化顺序按照定义的顺序进行。

3、static代码块

  • 静态代码块的使用可以优化程序的性能,static块可以置于类中的任何位置,同样类中可以存在多个static代码块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只执行一次。

父类

public class staticBase {
	static {
		System.out.println("staticBase---父类中的静态代码块加载。。。");
	}
	public staticBase() {
		System.out.println("staticBase---父类中的构造函数加载。。。");
	}
}

子类


public class staticTest extends staticBase{
	public String test = "成员变量";
	static {
		System.out.println("staticTest---本类中的静态代码块加载。。。");
		staticTest statictest = new staticTest();
		System.out.println(statictest.test);
	}
	public staticTest() {
		System.out.println("staticTest---本类中的构造方法加载。。。");
	}
	public static void main(String[] args) {
		new staticTest();
	}
}

运行结果如下:

staticBase---父类中的静态代码块加载。。。
staticTest---本类中的静态代码块加载。。。
staticBase---父类中的构造函数加载。。。
staticTest---本类中的构造方法加载。。。
成员变量
staticBase---父类中的构造函数加载。。。
staticTest---本类中的构造方法加载。。。

解析:

  • 在子类staticTest不生成实例的情况下(子类本身无构造方法重写和静态代码块),运行时只会执行父类的静态代码块。
  • 在子类staticTest生成实例的情况下,父类的构造方法被调用且静态代码块也被执行。
  • 运行结果的解析:子类和父类的构造方法均被重写,在staticTest生成实例的时候分别调用了父类staticBase和自身的构造方法。在static块中调用非静态的成员变量,需要生成对象的实例才能完成调用。在生成子类对象staticTest的实例的过程中,分别调用了父类对象和自身的构造方法。当类被加载的时候,静态代码块只执行一次,所以第二次生成对象的实例的时候,运行结果没有出现父类和子类静态代码块的打印信息。
  • 执行顺序:父类静态代码块 ->子类静态代码块 ->父类构造方法 ->子类构造方法 ->子类静态代码块中访问非静态成员变量,通过生成子类实例访问。->生成子类实例的过程中分别调用了父类和子类的构造方法。

静态内部类

  • 静态内部类可以声明:静态变量、静态常量、普通变量、普通常量。

  • 静态内部类不能直接访问外部类中的非静态变量或常量,需要生成外部类的实例对象,才能调用。

  • 静态内部类可以直接调用外部类的构造方法、静态方法

    外部类调用静态内部类的两种情况

    情况一

    
    public class Outter {
    	
    	private static final String static_final_outter = "外部类-静态-常量";
    	private static String static_outter = "外部类-静态-变量";
    	private final String final_outter = "外部类-常量";
    	private String com_outter = "外部类-变量";
    //	外部类无参构造 
    	public Outter(String show) {
    		System.out.println("外部类-构造方法"+show);
    	}
    //	外部类普通方法
    	public void outterComMethod() {
    		System.out.println("外部类-普通方法");
    	}
    //	外部类静态方法
    	public static void outterStaticMethod(String show) {
    		System.out.println("外部类-静态方法"+show);
    	}
    //	静态内部类
    	public static class Inner{
    		static final String static_final_inner = "内部类-静态-常量";
    		static String static_inner = "内部类-静态-变量";
    		private final String final_inner = "内部类-常量";
    		private String com_inner = "内部类-变量";
    //		内部类无参构造
    		public Inner() {
    			System.out.println("内部类-无参构造");
    		}
    //		内部类普通方法
    		public void inenerComMethod() {
    			System.out.println("内部类-普通方法");
    		}
    //		内部类静态方法
    		public static void inenerStaticMethod(String show) {
    			System.out.println("内部类-静态方法"+show);
    		}
    //		内部类访问外部类
    		public void getOutter() {
    			System.out.println(static_final_outter+"-被内部类Inner调用");
    			System.out.println(static_outter+"-被内部类Inner调用");
    			new Outter("-被内部类Inner调用");
    			outterStaticMethod("-被内部类Inner调用");
    //			new Outter("").outterComMethod();
    //			如下不能直接调用,可生成外部类的实例对象调用
    //			System.out.println(new Outter("").final_outter+"-被内部类Inner调用");
    //			System.out.println(new Outter("").com_outter+"-被内部类Inner调用");
    		}
    	}
    	public static void main(String[] args) {
    //		本类外部类调用内部类
    		new Inner().getOutter();
    		//在外部类中调用内部类的构造方法
    		new Inner();
    		//外部类调用内部类的静态常量、静态变量、静态方法
    		System.out.println(Inner.static_final_inner+"-被外部类Outter调用");
    		System.out.println(Inner.static_inner+"-被外部类Outter调用");
    		Inner.inenerStaticMethod("-被外部类Outter调用");
    		new Inner().inenerComMethod();
    		
    	}
    
    }
    

    运行结果如下

    内部类-无参构造
    外部类-静态-常量-被内部类Inner调用
    外部类-静态-变量-被内部类Inner调用
    外部类-构造方法-被内部类Inner调用
    外部类-静态方法-被内部类Inner调用
    内部类-无参构造
    内部类-静态-常量-被外部类Outter调用
    内部类-静态-变量-被外部类Outter调用
    内部类-静态方法-被外部类Outter调用
    内部类-无参构造
    内部类-普通方法
    

情况二

import info.StaticFather;

public class Base  {
	public static void main(String[] args) {
//		外部类调用静态内部类
		Outter.Inner oi = new Outter.Inner();
		oi.getOutter();
		//在外部类中调用内部类的构造方法
		new Outter.Inner();
		//外部类调用内部类的静态常量、静态变量、静态方法
		System.out.println(Outter.Inner.static_final_inner+"-被外部类Outter调用");
		System.out.println(Outter.Inner.static_inner+"-被外部类Outter调用");
		Outter.Inner.inenerStaticMethod("-被外部类Outter调用");
		oi.inenerComMethod();
	}
}

运行结果如下

内部类-无参构造
外部类-静态-常量-被内部类Inner调用
外部类-静态-变量-被内部类Inner调用
外部类-构造方法-被内部类Inner调用
外部类-静态方法-被内部类Inner调用
内部类-无参构造
内部类-静态-常量-被外部类Outter调用
内部类-静态-变量-被外部类Outter调用
内部类-静态方法-被外部类Outter调用
内部类-普通方法
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值