java—调整方法的返回值,该方法是单例的,并且具有最终访问修饰符

xqkwcwgp  于 2021-06-30  发布在  Java
关注(0)|答案(2)|浏览(393)

我想从一个示例类中调整一个方法的返回值,我不太确定是否有反射。我想不通,所以我想在这里问一下。例如,假设我有以下类foo:

public final class Foo {

    private static final INSTANCE = new Foo()

    protected Foo() {}

    public final String getName() {
        return "Foo";
    }

    public static Foo getInstance() {
        return INSTANCE;
    }

}

一些背景:
foo类来自外部库
foo类不可调整
foo类不可扩展
因此,在这个基本示例中,我希望从getname()方法而不是foo获得返回的bar。非常明确地说:

Foo foo = Foo.getInstance();
String name = foo.getName();
System.out.println(name) // --> prints "Bar"

为什么我需要这个?
我需要把foo的这个示例传递给另一个只接受foo类型的对象的方法。此方法将调用方法getname(),并执行一些额外的计算。
实际用例:
我会尽量给出更多的背景,希望能更清楚一点。生成器类中有一个方法正在接受的示例 KeyManagerFactory 一个名为 setKeyManagerFactory(KeyManagerFactory keyManagerFactory) . 此生成器类将在内部调用 getKeyManagers 在keymanagerfactory上,它将返回 KeyManagers[] keymanagerfactory是最后一个类,它根本没有公共构造函数。getkeymanager方法也是最终的。我已经有一个 KeyManager[] 所以我想破解这个keymanagerfactory,返回我自己的数组,而不是我自己的keymanagers,并将其提供给构建器。
通常,keymanagerfactory用以下代码段示例化:

KeyStore keyStore = ... //initialized keyStore
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
kmf.init(keyStore, keyPassword);

KeyManager[] keyManagers = kmf.getKeyManagers();

通过上面的代码片段,keymanagerfactory将基于提供的keystore对象返回keymanager数组。我想要实现的是以某种方式返回我的自定义keymanager数组。
我还添加了keymanagerfactory的反编译源代码:

package javax.net.ssl;

import java.security.AccessController;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivilegedAction;
import java.security.Provider;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import sun.security.jca.GetInstance;
import sun.security.jca.GetInstance.Instance;

public class KeyManagerFactory {
    private Provider provider;
    private KeyManagerFactorySpi factorySpi;
    private String algorithm;

    public static final String getDefaultAlgorithm() {
        String var0 = (String)AccessController.doPrivileged(new PrivilegedAction<String>() {
            public String run() {
                return Security.getProperty("ssl.KeyManagerFactory.algorithm");
            }
        });
        if (var0 == null) {
            var0 = "SunX509";
        }

        return var0;
    }

    protected KeyManagerFactory(KeyManagerFactorySpi var1, Provider var2, String var3) {
        this.factorySpi = var1;
        this.provider = var2;
        this.algorithm = var3;
    }

    public final String getAlgorithm() {
        return this.algorithm;
    }

    public static final KeyManagerFactory getInstance(String var0) throws NoSuchAlgorithmException {
        Instance var1 = GetInstance.getInstance("KeyManagerFactory", KeyManagerFactorySpi.class, var0);
        return new KeyManagerFactory((KeyManagerFactorySpi)var1.impl, var1.provider, var0);
    }

    public static final KeyManagerFactory getInstance(String var0, String var1) throws NoSuchAlgorithmException, NoSuchProviderException {
        Instance var2 = GetInstance.getInstance("KeyManagerFactory", KeyManagerFactorySpi.class, var0, var1);
        return new KeyManagerFactory((KeyManagerFactorySpi)var2.impl, var2.provider, var0);
    }

    public static final KeyManagerFactory getInstance(String var0, Provider var1) throws NoSuchAlgorithmException {
        Instance var2 = GetInstance.getInstance("KeyManagerFactory", KeyManagerFactorySpi.class, var0, var1);
        return new KeyManagerFactory((KeyManagerFactorySpi)var2.impl, var2.provider, var0);
    }

    public final Provider getProvider() {
        return this.provider;
    }

    public final void init(KeyStore var1, char[] var2) throws KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException {
        this.factorySpi.engineInit(var1, var2);
    }

    public final void init(ManagerFactoryParameters var1) throws InvalidAlgorithmParameterException {
        this.factorySpi.engineInit(var1);
    }

    public final KeyManager[] getKeyManagers() {
        return this.factorySpi.engineGetKeyManagers();
    }
}
ct3nt3jp

ct3nt3jp1#

你可以这样做(对于私有字段,可以使用setaccessible(true)

public final class  Single {
    public String s;

    public Single() {
    }

    public String getS() {
        return s;
    }
}

public class Main {
    public static void main(String[] args) throws IllegalAccessException {
        Single single = new Single();
        single.getClass().getFields()[0].set(single, "Hmm");
        System.out.println(single.getS());
    }
}
juzqafwq

juzqafwq2#

有了@tgdavies的提示,我就能完成我想要的。谢谢您!
所以我创造了一个 KeyManagerFactoryWrapper 其中包含一个自定义 KeyManagerFactorySpi 打电话 KeyManagerFactorySpiWrapper .

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.KeyManagerFactorySpi;
import javax.net.ssl.ManagerFactoryParameters;
import java.security.KeyStore;
import java.security.Provider;

/**
 * @author Hakan Altindag
 */
public class KeyManagerFactoryWrapper extends KeyManagerFactory {

    private static final String KEY_MANAGER_FACTORY_ALGORITHM = "no-algorithm";
    private static final Provider PROVIDER = new Provider("", 1.0, "") {};

    public KeyManagerFactoryWrapper(KeyManager keyManager) {
        super(new KeyManagerFactorySpiWrapper(keyManager), PROVIDER, KEY_MANAGER_FACTORY_ALGORITHM);
    }

    private static class KeyManagerFactorySpiWrapper extends KeyManagerFactorySpi {

        private final KeyManager[] keyManagers;

        public KeyManagerFactorySpiWrapper(KeyManager keyManager) {
            this.keyManagers = new KeyManager[]{keyManager};
        }

        @Override
        protected void engineInit(KeyStore keyStore, char[] keyStorePassword) {
            // ignoring
        }

        @Override
        protected void engineInit(ManagerFactoryParameters managerFactoryParameters) {
            // ignoring
        }

        @Override
        protected KeyManager[] engineGetKeyManagers() {
            return keyManagers;
        }
    }
}

我在trustmanagerfactory上也做到了这一点:

import javax.net.ssl.ManagerFactoryParameters;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.TrustManagerFactorySpi;
import java.security.KeyStore;
import java.security.Provider;

/**
 * @author Hakan Altindag
 */
public class TrustManagerFactoryWrapper extends TrustManagerFactory {

    private static final String KEY_MANAGER_FACTORY_ALGORITHM = "no-algorithm";
    private static final Provider PROVIDER = new Provider("", 1.0, "") {};

    public TrustManagerFactoryWrapper(TrustManager trustManager) {
        super(new TrustManagerFactorySpiWrapper(trustManager), PROVIDER, KEY_MANAGER_FACTORY_ALGORITHM);
    }

    private static class TrustManagerFactorySpiWrapper extends TrustManagerFactorySpi {

        private final TrustManager[] trustManagers;

        public TrustManagerFactorySpiWrapper(TrustManager trustManager) {
            this.trustManagers = new TrustManager[]{trustManager};
        }

        @Override
        protected void engineInit(KeyStore keyStore) {
            // ignoring
        }

        @Override
        protected void engineInit(ManagerFactoryParameters managerFactoryParameters) {
            // ignoring
        }

        @Override
        protected TrustManager[] engineGetTrustManagers() {
            return trustManagers;
        }
    }   
}

现在,我可以使用以下代码片段轻松地在keymanagerfactory和trustmanagerfactory中创建一个示例:

KeyManager keyManager = ...; //initialised keyManager
TrustManager trustManager = ...; //initialised trustManager

KeyManagerFactory = new KeyManagerFactoryWrapper(keyManager);
TrustManagerFactory = new TrustManagerFactoryWrapper(keyManager);

相关问题