【问题标题】:What's the advantage of making an inner class as static with Java?使用 Java 将内部类设为静态有什么好处?
【发布时间】:2013-04-15 08:56:13
【问题描述】:

我的 Java 类中有一个内部类。

当我运行find bugs 时,它建议(警告)将其设为静态。

这个警告有什么意义?将内部类设为静态有什么好处?

【问题讨论】:

标签: java class findbugs


【解决方案1】:

静态内部类的好处:

  1. 静态内部类的实例化不依赖于外部类指导,以及实例化的内存开销。
  2. 静态内部类不持有外部类引导,不影响外部类的集合,避免外部类在内存生存时间的延长导致内存泄漏。

【讨论】:

    【解决方案2】:

    我们已经有了很好的答案,这是我的 5 美分:

    当我们需要分离逻辑功能但使用外部类的方法和变量时,会使用静态和非静态内部类。两个内部类都可以访问外部类的私有变量。

    静态内部类的优点: 1)静态类可以从外部类访问静态变量 2) 静态类可以视为独立类

    非静态内部类: 1) 不能使用外部类的静态成员 2) 不能被视为一个独立的类

    public class NestedClassDemo {
        private int a = 100;
        int b = 200;
        private static int c = 500;
    
        public NestedClassDemo() {
            TestInnerStatic teststat = new TestInnerStatic();
            System.out.println("const of NestedClassDemo, a is:"+a+", b is:"+b+".."+teststat.teststat_a);
        }
    
        public String getTask1(){
            return new TestInnerClass().getTask1();
        }
    
        public String getTask2(){
            return getTask1();
        }
    
    
        class TestInnerClass{
            int test_a = 10;
    
            TestInnerClass() {
                System.out.println("const of testinner private member of outerlcass"+a+"..."+c);
            }
            String getTask1(){
                return "task1 from inner:"+test_a+","+a;
            }
        }
    
        static class TestInnerStatic{
            int teststat_a = 20;
    
            public TestInnerStatic() {
                System.out.println("const of testinnerstat:"+teststat_a+" member of outer:"+c);
            }
    
            String getTask1stat(){
                return "task1 from inner stat:"+teststat_a+","+c;
            }
        }
    
        public static void main(String[] args){
            TestInnerStatic teststat = new TestInnerStatic();
            System.out.println(teststat.teststat_a);
            NestedClassDemo nestdemo = new NestedClassDemo();
            System.out.println(nestdemo.getTask1()+"...."+nestdemo.getTask2());
        }
    }
    

    从外部访问静态内部和非静态内部类:

    public class TestClass {
        public static void main(String[] args){
            NestedClassDemo.TestInnerClass a = new NestedClassDemo().new TestInnerClass();
            NestedClassDemo.TestInnerStatic b = new NestedClassDemo.TestInnerStatic();
        }
    }
    

    静态内部类的官方java文档可以在https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html找到

    【讨论】:

      【解决方案3】:

      静态内部类在语义上更简单。它就像一个顶级课程,只是您有更多的可见性选项(例如,您可以将其设为私有)。

      避免使用非静态内部类的一个重要原因是它们更复杂。有对外部类的隐藏引用(甚至可能不止一个)。内部类的方法中的简单名称现在可能是以下三种情况之一:本地、字段或外部类的字段。

      这种复杂性的一个产物是对外部类的隐藏引用可能导致内存泄漏。假设内部类是一个侦听器,并且可能是一个静态内部类。只要注册了侦听器,它就会持有对外部类实例的引用,而外部类的实例又可能会占用大量内存。将侦听器设为静态可能允许对外部实例进行垃圾回收。

      【讨论】:

        【解决方案4】:

        非静态内部类具有对外部类的隐式引用。如果将类设为静态,则可以节省一些内存和代码。

        【讨论】:

          【解决方案5】:

          默认情况下,内部类具有对外部类对象的隐式引用。如果您从外部类的代码中实例化 this 的对象,这一切都为您完成。如果您不这样做,则需要自己提供对象。

          静态内部类没有这个。

          这意味着它可以在外部类对象的范围之外实例化。这也意味着如果你“导出”内部类的一个实例,它不会阻止当前对象被收集。

          作为一项基本规则,如果内部类没有理由访问外部类,则应默认将其设为静态。

          【讨论】:

          • 我喜欢你定义的基本规则。
          【解决方案6】:

          如果嵌套类不访问封闭类的任何变量,则可以将其设为静态。这样做的好处是您不需要外部类的封闭实例来使用嵌套类。

          【讨论】:

          • +1 我刚刚在我的 Potion 类中创建一个 Mana Potion 时遇到了这个问题,但忘记将其声明为静态,因此无法声明 new ManaPotion()。
          • @arynaq - 继承是一个强有力的指标,表明ManaPotion 应该Potion 的内部类。一个很好的正面例子是Map 使用Map.Entry 实例来保存其条目。 Potion 会使用 Potion.ManaPotion 吗?这甚至适用于静态内部类。
          • 没错,这是为了测试,这几乎是我唯一一次使用嵌套类。
          猜你喜欢
          • 2011-07-12
          • 1970-01-01
          • 1970-01-01
          • 2011-01-27
          • 2023-03-20
          • 2012-06-29
          • 2018-10-20
          • 2021-10-01
          相关资源
          最近更新 更多