私有类的公共构造函数

26

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

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

        }
    }
}

我不认为有任何好的理由让那个构造函数成为“public”。将构造函数设为“private”会产生同样的效果,并且会更清楚地表达您的意图。 - Mattias Buelens
这个答案可能会有关联:https://dev59.com/7mAg5IYBdhLWcg3w0Nkz#23161623 - Octavia Togami
2个回答

16

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

// 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
    }
}

实际上,在这种情况下,默认受保护的可见性就足以创建一个实例。所有非私有修饰符都允许您从同一包中的其他类创建实例,但实际上具有相同的可见性。
  • 私有类对于包外的类不可见,因此公共方法在这里没有用处。
  • 私有类不能被包外的类扩展,因此受保护的也没有用处。
  • 即使使用反射,公共构造函数默认情况下也无法从其他包访问,并且会抛出IllegalAccessException。它首先检查类的可见性,然后检查成员的可见性。

默认修饰符是最限制性的修饰符,允许您直接从其他类调用构造函数,因此包级私有似乎是构造函数和任何其他非私有方法最适合的可见性。这也具有一个优点,即如果将来更改类的可见性,则不会意外地将构造函数或任何方法暴露给公众。


Y() 函数设为私有函数会更清晰、更整洁。 - assylias

8
你知道的,每次我创建一个私有内部类时,我都会问自己这个问题,但是我总是认为可能存在一些(可能是牵强的)公共构造函数的理由。所以@kapep的答案让我感到兴奋,并鼓励我寻找在私有内部类中要求公共构造函数的方法,但是我越想越觉得这种方法存在漏洞。
所有可能的角度都失败了:
  • Serialisation: When unmarshalling an object whose superclass is not serializable, the superclass needs a no-arg constructor accessible from the subclass. So, protected should always suffice here.

  • Reflective tools: Code that uses reflection to get the inner class constructor through a returned instance. Fails because the type visibility is checked first, as @kapep pointed out, though it leaves a rather interesting error message:

    Exception in thread "main" java.lang.IllegalAccessException: Class A can not access a member of class contrived.B$C with modifiers "public"

  • Inner class extension shenanigans: Don't try this at home:

    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();
      }
    }
    

    Seemed promising at first, but I didn't get too far with that one.


最终,我找不到一种使私有内部类上的公共构造函数有用的方法。

那么为什么尽管没有任何用途,这在技术上是合法的呢?可能是因为当没有提供其他构造函数时,编译器会自动插入一个无参的公共构造函数。因此,语言不应该禁止这些构造。虽然更像是一种产物而不是原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接