最近在复习回顾 Java 的学习,然后就变复习,边整理总结。
static 关键字 很常见,想想用法无非是两种情况:
1.为某特定数据类型或对象分配单一的存储空间。
2.实现某个方法或属性与类而不是对象关联在一起
这两种 都是为了避开 与对象的关联。
所以简言之,static 是跟类有关的,跟对象没关系,下面再详细的说:
具体的代码来说 ,static 主要有 4 中使用情况:成员变量、成员方法、代码块和内部类
1) 成员变量
成员变量分为 静态变量 和 实例变量。
很好的理解就是只要加了 static ,
那么这个变量就属于类,他跟对象是没有关系的。只要静态变量所在的类被加载,这个静态变量就会被分配空间,因此就可以被使用了。对静态变量的引用有两种方式,分别是“类.静态变量"和”对象.静态变量"
实例变量属于对象,只有对象被创建后,实例变量才会被分配内存空间,才能被使用,它在内存中存在多个复制,只有用“对象.实例变量”的方式来引用。
2) 成员方法
static 方法是类的方法,不需要创建对象就可以被调用,而非 static 方法是对象的方法,只有对象被创建出来后才可以被使用。
static 方法中不能使用 this 和 super 关键字,不能调用非 static 方法,只能访问所属类的静态成员变量和成员方法,因为当 static 方法被调用时,这个类的对象可能还没被创建,即使已经被创建了,也无法确定调用哪个对象的方法。同理,static 方法也不能访问非 static 类型的变量。
关于 static 修饰的方法,最常用的就是单例设计模式,一开始我们在学设计模式的时候就遇到。
public class SingleTest { // 创建对象的变量 private static SingleTest install = null; // 私有化构造函数 private SingleTest() { System.out.println("123456"); } // 创建对象的方法 public static SingleTest getInstance() { if (install == null) { install = new SingleTest(); } return install; } }
这样 其他的类要想访问 SingleTest 就只能通过 SingleTest.getInstance();对外暴露的方法来访问这个对象。
3) 代码块
static 代码块在类中是独立于成员变量和成员函数的代码块的,所以这代码块只会被执行一次。
测试代码如下。
public class Test { // 静态变量 private static int a = 0; static { a = 10; System.out.println("静态代码块 a =" + a); } { a = 20; System.out.println("非静态代码块 a =" + a); } public Test() { System.out.println("无参构造方法在执行a=" + a); } public Test(String string) { System.out.println("带参构造方法中的值 string = " + string); System.out.println("带参构造方法中的值 a =" + a); } public static void main(String[ ] args) { Test test = null; System.out.println("---------------------"); test = new Test(); Test test2 = new Test("带参"); } }
4) 内部类
内部类,按照名称来说就是类里面的类,static 关键字可以修饰内部类,但是不能修饰外部类。
静态 static 内部类和非静态的内部类的区别如下:
a) 内部静态类不需要有指向外部类的引用。但非静态内部类需要持有对外部类的引用。
b) 非静态内部类能够访问外部类的静态和非静态成员。静态类不能访问外部类的非静态成员。他只能访问外部类的静态成员。
c) 一个非静态内部类不能脱离外部类实体被创建,一个非静态内部类可以访问外部类的数据和方法,因为他就在外部类里面。
/** * * * Module: * * Outer.java * * @author c3gen * @since JDK 1.8 * @version 1.0 * @description: 测试内部类 */ public class Outer { private static String str = " test class "; public static class NestedStaticClass { // 静态内部类只能访问外部类的静态成员 public void privatePrintMsg() { // 试着将str改成非静态的,这将导致编译错误 System.out.println("静态内部类: " + str); } } // 非静态内部类 public class InnerClass { // 不管是静态方法还是非静态方法都可以在非静态内部类中访问 public void publicPrintMsg() { System.out.println("非静态内部类: " + str); } } public static void main(String[ ] args) { // 创建静态内部类的实例 Outer.NestedStaticClass nsc = new Outer.NestedStaticClass(); // 创建静态内部类的非静态方法 nsc.privatePrintMsg(); // 为了创建非静态内部类,我们需要外部类的实例 Outer outer = new Outer(); Outer.InnerClass inner = outer.new InnerClass(); // 调用非静态内部类的非静态方法 inner.publicPrintMsg(); // 我们也可以结合以上步骤,一步创建的内部类实例 Outer.InnerClass innerObject = new Outer().new InnerClass(); // 同样我们现在可以调用内部类方法 innerObject.publicPrintMsg(); } }
结果 :
静态内部类: test class
非静态内部类: test class
非静态内部类: test class
通过结果 我们可以分析 :非静态内部类是附属在外部类对象上的,需要先实例化一个外部类的对象,通过外部类对象才能实例化非静态内部类;而静态内部类可以看做是直接附属在外部类上的,这个静态代表附属体是外部类,而不是外部类实例;外部类在进程中是唯一的,而静态内部类不需要唯一,可以生成多个实例。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于