static class 静态类的实例化

一般情况下是不可以用static修饰类的。如果一定要用static修饰类的话,通常static修饰的是匿名内部类。

在一个类中创建另外一个类,叫做成员内部类。这个成员内部类可以静态的(利用static关键字修饰),也可以是非静态的。由于静态的内部类在定义、使用的时候会有种种的限制。所以在实际工作中用到的并不多。

在开发过程中,内部类中使用的最多的还是非静态地成员内部类。不过在特定的情况下,静态内部类也能够发挥其独特的作用。

  一、静态内部类的使用目的。

  在定义内部类的时候,可以在其前面加上一个权限修饰符static。此时这个内部类就变为了静态内部类。不过由于种种的原因,如使用上的限制等等因素(具体的使用限制,笔者在下面的内容中会详细阐述),在实际工作中用的并不是很多。但是并不是说其没有价值。在某些特殊的情况下,少了这个静态内部类还真是不行。如在进行代码程序测试的时候,如果在每一个Java源文件中都设置一个主方法(主方法是某个应用程序的入口,必须具有),那么会出现很多额外的代码。而且最主要的时这段主程序的代码对于Java文件来说,只是一个形式,其本身并不需要这种主方法。但是少了这个主方法又是万万不行的。在这种情况下,就可以将主方法写入到静态内部类中,从而不用为每个Java源文件都设置一个类似的主方法。这对于代码测试是非常有用的。在一些中大型的应用程序开发中,则是一个常用的技术手段。为此,这个静态内部类虽然不怎么常用,但是程序开发人员还必须要掌握它。也许在某个关键的时刻,其还可以发挥巨大的作用也说不定。

 

 

二、静态内部类的使用限制。

  将某个内部类定义为静态类,跟将其他类定义为静态类的方法基本相同,引用规则也基本一致。不过其细节方面仍然有很大的不同。具体来说,主要有如下几个地方要引起各位程序开发人员的注意。

  一是静态成员(包括静态变量与静态成员)的定义。一般情况下,如果一个内部类不是被定义成静态内部类,那么在定义成员变量或者成员方法的时候,是不能够被定义成静态成员变量与静态成员方法的。也就是说,在非静态内部类中不可以声明静态成员。如现在在一个student类中定义了一个内部类age,如果没有将这个类利用static关键字修饰,即没有定义为静态类,那么在这个内部类中如果要利用static关键字来修饰某个成员方法或者成员变量是不允许的。在编译的时候就通不过。故程序开发人员需要注意,只有将某个内部类修饰为静态类,然后才能够在这个类中定义静态的成员变量与成员方法。这是静态内部类都有的一个特性。也正是因为这个原因,有时候少了这个静态的内部类,很多工作就无法完成。或者说要绕一个大圈才能够实现某个用户的需求。这也是静态的内部类之所以要存在的一个重要原因。

  二是在成员的引用上,有比较大的限制。一般的非静态内部类,可以随意的访问外部类中的成员变量与成员方法。即使这些成员方法被修饰为private(私有的成员变量或者方法),其非静态内部类都可以随意的访问。则是非静态内部类的特权。因为在其他类中是无法访问被定义为私有的成员变量或则方法。但是如果一个内部类被定义为静态的,那么在银用外部类的成员方法或则成员变量的时候,就会有诸多的限制。如不能够从静态内部类的对象中访问外部类的非静态成员(包括成员变量与成员方法)。这是什么意思呢?如果在外部类中定义了两个变量,一个是非静态的变量,一个是静态的变量。那么在静态内部类中,无论在成员方法内部还是在其他地方,都只能够引用外部类中的静态的变量,而不能够访问非静态的变量。在静态内部类中,可以定义静态的方法(也只有在静态的内部类中可以定义静态的方法),在静态方法中引用外部类的成员。但是无论在内部类的什么地方引用,有一个共同点,即都只能够引用外部类中的静态成员方法或者成员变量。对于那些非静态的成员变量与成员方法,在静态内部类中是无法访问的。这就是静态内部类的最大使用限制。在普通的非静态内部类中是没有这个限制的。也正是这个原因,决定了静态内部类只应用在一些特定的场合。其应用范围远远没有像非静态的内部类那样广泛。

 三是在创建静态内部类时不需要将静态内部类的实例绑定在外部类的实例上。

通常情况下,在一个类中创建成员内部类的时候,有一个强制性的规定,即内部类的实例一定要绑定在外部类的实例中。也就是说,在创建内部类之前要先在外部类中要利用new关键字来创建这个内部类的对象。如此的话如果从外部类中初始化一个内部类对象,那么内部类对象就会绑定在外部类对象上。也就是说,普通非静态内部类的对象是依附在外部类对象之中的。但是,如果成员开发人员创建的时静态内部类,那么这就又另当别论了。通常情况下,程序员在定义静态内部类的时候,是不需要定义绑定在外部类的实例上的。也就是说,要在一个外部类中定义一个静态的内部类,不需要利用关键字new来创建内部类的实例。即在创建静态类内部对象时,不需要其外部类的对象。

 

具体为什么会这样,一般程序开发人员不需要了解这么深入,只需要记住有这个规则即可。在定义静态内部类的时候,千万不要犯画蛇添足的错误。

  从以上的分析中可以看出,静态内部类与非静态的内部类还是有很大的不同的。一般程序开发人员可以这么理解,非静态的内部类对象隐式地在外部类中保存了一个引用,指向创建它的外部类对象。不管这么理解,程序开发人员都需要牢记静态内部类与非静态内部类的差异。如是否可以创建静态的成员方法与成员变量(静态内部类可以创建静态的成员而非静态的内部类不可以)、对于访问外部类的成员的限制(静态内部类只可以访问外部类中的静态成员变量与成员方法而非静态的内部类即可以访问静态的也可以访问非静态的外部类成员方法与成员变量)。这两个差异是静态内部类与非静态外部类最大的差异,也是静态内部类之所以存在的原因。了解了这个差异之后,程序开发人员还需要知道,在什么情况下该使用静态内部类。如在程序测试的时候,为了避免在各个Java源文件中书写主方法的代码,可以将主方法写入到静态内部类中,以减少代码的书写量,让代码更加的简洁。


  总之,静态内部类在Java语言中是一个很特殊的类,跟普通的静态类以及非静态的内部类都有很大的差异。作为程序开发人员,必须要知道他们之间的差异,并在实际工作中在合适的地方采用合适的类。不过总的来说,静态内部类的使用频率并不是很高。但是在有一些场合,如果没有这个内部静态类的话,可能会起到事倍功半的反面效果

 

 

 

------------------------------------------------------------------------------------------------------------------------------------

 


看了以上内容后,下面我整体测试了一下:

 


首先大家需要明白,静态内部类只是不依附与外部类,它里面的变量和方法也没有说一定得是静态的,下面拿代码说事:

public class Test {
 public  static void main(String[] args){
  MyInnerStaticClass inner=new MyInnerStaticClass();
  inner.a=10;
  inner.b="abc";
  System.out.println(inner.a+" "+inner.b);
 }
 
 
 static class MyInnerStaticClass{
  int a;
  String b;
 }
}
上述代码将静态匿名类用new实例化了,运行后输入10 abc,正确!

 


再看一个代码:

public class Test { 
    public  static void main(String[] args){  
        MyInnerStaticClass inner=null; 
        inner.a=10; 
        inner.b="abc"; 
        System.out.println(inner.a+" "+inner.b); 
    } 
 
    static class MyInnerStaticClass{ 
        int a; 
        String b; 
    } 


代码中的

MyInnerStaticClass inner=null;替换为

MyInnerStaticClass inner;后提示没有初始化,然后我就将其附为null,结果eclipse在inner.a=10处提示

Null pointer access: The variable inner can only be null at this location

这充分说明了静态内部类中的变量不是默认是静态的,运行结果是

java.lang.NullPointerException

下面一个代码更能说明问题

public class Test {
 public  static void main(String[] args){
  MyInnerStaticClass inner=null;
  inner.a=10;
  inner.b="abc";
  System.out.println(inner.a+" "+inner.b);
 }


 static class MyInnerStaticClass{
  static int a;
  static String b;
 }
}
这个代码运行就正确了,说明静态内部类其实和定义在外面的单独一个普通类区别不大,但是大家还是需要理解上面引用的那篇文章里说的,毕竟他是内部类,还是有一些和外部类不同的

虽然这个代码运行成功了,但是eclipse提示了一个警告

The static field Test1.MyInnerStaticClass.a should be accessed in a static way


这个大家都懂得,类中的静态方法和变量不属于单独一个实例,所以访问时应该直接classname.var方式访问,当前上面方法也不错,但是不好,改正后代码

public class Test { 

    public  static void main(String[] args){  
        MyInnerStaticClass.a=10; 
        MyInnerStaticClass.b="abc"; 
        System.out.println(MyInnerStaticClass.a+" "+MyInnerStaticClass.b); 
    } 
 
 
    static class MyInnerStaticClass{ 
        static int a; 
        static String b; 
    } 


<think>我们讨论的是如何获取一个类的静态属性。在Java中,获取类的静态属性并不需要实例化该类。因为静态属性属于类本身,而不是类的实例。我们可以直接通过类名来访问静态属性,或者在反射中使用类对象来访问。但是,如果使用反射机制来访问静态属性,我们同样不需要创建类的实例。只需要获取该类的Class对象,然后通过反射API来访问字段即可。以下是详细步骤和代码示例:1.获取目标类的Class对象。可以通过类名.class或者Class.forName("全限定类名")。2.使用getDeclaredField或getField方法获取字段对象(Field)。注意:getField只能获取public字段,而getDeclaredField可以获取所有声明的字段(包括private),但需要设置可访问性。3.由于是静态字段,在获取字段值的时候,不需要传入具体的实例对象,可以传入null。示例代码:假设有一个类Data,其中包含一个静态属性:```javapublicclassData{publicstaticintstaticField=42;}```现在我们要通过反射获取这个静态属性值:```javaimportjava.lang.reflect.Field;publicclassReflectionStaticField{publicstaticvoidmain(String[]args){try{//1.获取Class对象Class<?>clazz=Class.forName("Data");//2.获取字段对象Fieldfield=clazz.getDeclaredField("staticField");//3.因为是静态字段,所以不需要实例,使用nullintvalue=(int)field.get(null);System.out.println("静态字段的值:"+value);//输出:42}catch(ClassNotFoundException|NoSuchFieldException|IllegalAccessExceptione){e.printStackTrace();}}}```解释:-在调用`field.get(null)`时,传入null表示这是一个静态字段,不需要实例。-如果字段是private的,我们需要先设置可访问性:`field.setAccessible(true);`另外,对于非静态字段,我们就需要先创建类的实例,然后通过实例来获取字段值。所以,总结:获取静态属性不需要实例化类。相关问题:§§相关问题§§:1.如何通过反射修改一个类的静态属性?2.在反射中,如何获取一个类的所有静态字段?3.反射访问私有静态字段时需要注意什么?4.静态字段的加载时机是什么时候?反射获取静态字段是否会触发类加载?</think> # 获取类的静态属性:需要实例化类吗? 在Java中,**获取类的静态属性不需要实例化类**。静态属性(static fields)属于类本身,而不是类的实例。我们可以直接通过类名访问静态属性,而不需要创建对象实例。 ## 获取静态属性的方法 ### 1. 直接通过类名访问(最简单方式) ```java public class Data { public static SynchronizedList<Bancai> bancais = new SynchronizedList<>(Bancai.class); } // 直接访问 SynchronizedList<Bancai> list = Data.bancais; ``` ### 2. 使用反射(当字段名动态确定时) 即使使用反射,也不需要实例化类: ```java import java.lang.reflect.Field; public class ReflectionExample { public static void main(String[] args) { try { // 1. 获取Data类的Class对象 Class<?> clazz = Class.forName("your.package.Data"); // 2. 获取静态字段(不需要实例) Field bancaisField = clazz.getDeclaredField("bancais"); // 3. 获取字段的值(静态字段,传null即可) SynchronizedList<?> bancaisList = (SynchronizedList<?>) bancaisField.get(null); System.out.println("获取到 bancais 属性"); } catch (Exception e) { e.printStackTrace(); } } } ``` ### 3. 处理私有静态属性 如果静态属性是私有的,需要使用`setAccessible(true)`: ```java public class ReflectionPrivate { public static void main(String[] args) { try { Class<?> clazz = Class.forName("your.package.Data"); // 获取私有静态字段 Field privateField = clazz.getDeclaredField("privateStaticField"); // 设置可访问 privateField.setAccessible(true); // 获取值(传null) Object value = privateField.get(null); System.out.println("私有静态属性值: " + value); } catch (Exception e) { e.printStackTrace(); } } } ``` ## 为什么不需要实例化? 1. **静态属性的特性**: - 静态属性属于类本身,不依赖于任何实例 - 在类加载时初始化,生命周期与类相同 2. **JVM内存模型**: - 静态属性存储在方法区(Method Area) - 实例属性存储在堆内存(Heap) 3. **访问机制**: - 直接访问:`ClassName.fieldName` - 反射访问:`field.get(null)`(传入`null`表示静态字段) ## 何时需要实例化? **只有在处理非静态实例属性时才需要创建对象实例**: ```java public class Data { public String instanceField; // 实例属性 } // 访问实例属性需要先创建实例 Data obj = new Data(); String value = obj.instanceField; // 或者反射访问 Field instanceField = clazz.getDeclaredField("instanceField"); Object value = instanceField.get(obj); // 这里需要传入具体的对象实例 ``` ## 最佳实践建议 1. 优先使用直接访问:`Data.bancais` 2. 当属性名需要在运行时确定时,使用反射 3. 处理私有属性时,确保代码有足够的安全权限 4. 在多线程环境中使用`setAccessible(true)`时,注意同步问题
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值