私有类的公共构造函数

时间:2014-04-20 09:19:20

标签: java constructor

我是Java新手。我想知道在私有类中使用 public 构造函数是什么。类中的私有类可以从同一个类初始化,那么将私有类的构造函数公开为什么呢?

public class MainActivity extends Activity {
     private class AcceptThread extends Thread {
        public AcceptThread() {

        }
    }
}

2 个答案:

答案 0 :(得分:14)

对于具有私有类的公共或受保护修饰符,似乎没有任何实际用例。如果您在单个文件中有多个类(但不是嵌套或本地),则需要非私有构造函数来实例化私有类。

// X.java

public class X {
    private Y y = new Y();
}

class Y {
    Y () {
        // if this were private, X wouldn't be able to create an instance of Y
    }
}

实际上默认protected可见性足以在这种情况下创建实例。所有非私有修饰符都允许您从同一个包中的其他类创建实例,但实际上具有相同的可见性。

  • 私有类对包外的类不可见,因此public方法在此处没有用。
  • 私有类不能通过包外的类进行扩展,因此protected也没有用。
  • 即使使用反射,默认情况下也不能从其他包中访问公共构造函数,并抛出IllegalAccessException。它首先检查类可见性,然后检查成员可见性。

默认修饰符是限制性最强的修饰符,允许您直接从其他类调用构造函数,因此package-private似乎是构造函数以及任何其他非适当的可见性。私人方法。这样做的另一个好处是,如果您将来更改类可见性,则不会意外地将构造函数或任何方法暴露给公众。

答案 1 :(得分:6)

你知道,我几乎每次创建私人内部课时都会问自己这个问题,但我总是认为公共构造函数可能有一些(可能是人为的)理由。所以@kapep的回答让我感到刺痛,并鼓励他找到在私人内部课堂上要求公共构造函数的方法,但是我想的越多越好,我认为漏洞就越多。

可能的角度,所有这些都让我失望:

  • 序列化 :当解组其超类不可序列化的对象时,超类需要一个可从子类访问的无参数构造函数 。所以,protected应该总是足够了。

  • 反射工具 :使用反射通过返回的实例获取内部类构造函数的代码。失败,因为首先检查类型可见性,正如@kapep指出的那样,尽管它留下了一个相当有趣的错误消息:

      

    线程“main”中的异常java.lang.IllegalAccessException:类A无法访问类的设计成员.B $ C,修饰符为“public”

  • 内部类扩展恶作剧 :请勿在家中尝试:

    package a;
    class Outer {
      private class Inner {
      }
    }
    
    package b;
    // compile error: Outer.Inner has private access in Outer
    class Extender extends a.Outer.Inner {
      Extender(a.Outer outer) {
        outer.super();
      }
    }
    

    起初看起来很有希望,但我对这一点并没有太远。


最后,我找不到在私有内部类有用上创建公共构造函数的方法。

那为什么这在技术上是合法的,尽管没有用?可能是因为当没有提供其他构造函数时,编译器会自动插入一个无参数的公共构造函数。因此,语言不应该禁止这种结构。但更多的是人工制品而不是理由。