如何访问类的私有构造函数?

gmh*_*mhk 68 java oop constructor instance

我是一名Java开发人员.在一次采访中,我被问到一个关于私人建筑师的问题:

你可以访问类的私有构造函数并实例化它吗?

我回答'不',但错了.

你能解释为什么我错了,举一个用私有构造函数实例化对象的例子吗?

Joa*_*uer 83

绕过限制的一种方法是使用反射:

import java.lang.reflect.Constructor;

public class Example {
    public static void main(final String[] args) throws Exception {
        Constructor<Foo> constructor = Foo.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        Foo foo = constructor.newInstance();
        System.out.println(foo);
    }
}

class Foo {
    private Foo() {
        // private!
    }

    @Override
    public String toString() {
        return "I'm a Foo and I'm alright!";
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @maryanne它只是在输出中使结果更明显.这不是必需的. (3认同)

Jon*_*eet 70

  • 您可以在类本身内访问它(例如,在公共静态工厂方法中)
  • 如果它是嵌套类,则可以从封闭类访问它
  • 根据适当的权限,您可以使用反射访问它

现在还不清楚这些是否适用 - 你能提供更多信息吗?


ton*_*nio 20

这可以使用反射来实现.

考虑使用私有构造函数的类Test:

Constructor<?> constructor  = Test.class.getDeclaredConstructor(Context.class, String[].class);
Assert.assertTrue(Modifier.isPrivate(constructor.getModifiers()));
constructor.setAccessible(true);
Object instance = constructor.newInstance(context, (Object)new String[0]);
Run Code Online (Sandbox Code Playgroud)


gpr*_*our 7

关于访谈中私人建筑商的第一个问题是,

我们可以在一个类中拥有私有构造函数吗?

而有时候候选人给出的答案是,不,我们不能拥有私人建设者.

所以我想说,是的,你可以在课堂上拥有私人建筑师.

这没什么特别的,试着这样想,

私人:私人的任何东西都只能在课堂上访问.

构造函数:一个与类名相同的方法,在创建类的对象时隐式调用它.

或者你可以说,要创建一个你需要调用它的构造函数的对象,如果没有调用构造函数,那么就无法实例化对象.

这意味着,如果我们在一个类中有一个私有构造函数,那么它的对象只能在类中实例化.因此,用简单的话来说,如果构造函数是私有的,那么你将无法在类之外创建它的对象.

有什么好处 这个概念可以用来实现单例对象(这意味着只能创建一个类的对象).

请参阅以下代码,

class MyClass{
    private static MyClass obj = new MyClass();

    private MyClass(){

    }

    public static MyClass getObject(){
        return obj;
    }
}
class Main{
    public static void main(String args[]){

        MyClass o = MyClass.getObject();
        //The above statement will return you the one and only object of MyClass


        //MyClass o = new MyClass();
        //Above statement (if compiled) will throw an error that you cannot access the constructor.

    }
}
Run Code Online (Sandbox Code Playgroud)


Cap*_*tti 5

我喜欢上面的答案,但是还有两种更漂亮的方法可以创建具有私有构造函数的类的新实例。这一切都取决于您想要实现的目标以及在什么情况下。

1:使用Java检测ASM

那么在这种情况下,您必须使用转换器启动 JVM。为此,您必须实现一个新的 Java 代理,然后让这个转换器为您更改构造函数。

首先创建类转换器。这个类有一个叫做transform的方法。覆盖此方法,在此方法中,您可以使用 ASM类读取器和其他类来操作构造函数的可见性。转换器完成后,您的客户端代码将可以访问构造函数。

您可以在此处阅读更多相关信息:使用 ASM 更改私有 Java 构造函数

2:重写构造函数代码

好吧,这并不是真正访问构造函数,但您仍然可以创建一个实例。假设您使用第三方库(比如 Guava)并且您可以访问代码,但由于某种原因您不想更改 JVM 加载的 jar 中的代码(我知道,这是不是很逼真,但让我们假设代码在像 Jetty 这样的共享容器中,并且您无法更改共享代码,但是您有单独的类加载上下文)然后您可以使用私有构造函数制作第 3 方代码的副本,更改在您的代码中将私有构造函数设置为 protected 或 public,然后将您的类放在类路径的开头。从那时起,您的客户端可以使用修改后的构造函数并创建实例。

后一种更改称为链接接缝,这是一种接缝,其中启用点是类路径。