当前位置: 首页 > 知识库问答 >
问题:

调整作为单例且具有最终访问修饰符的方法的返回值

郑俊美
2023-03-14

我想从实例类调整方法的返回值,但我不太确定是否可以使用或不使用反射。我想不通,所以我想在这里问一下。假设我有以下类 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() 并执行一些额外的计算。

实际使用案例:

我会试着给出更多的背景,希望会更清楚一点。builder类中有一个方法接受< code>KeyManagerFactory的实例,该方法称为< code > setKeyManagerFactory(KeyManagerFactory KeyManagerFactory)。该构建器类将在内部调用KeyManagerFactory上的< code > get key manager ,并返回< code > key manager[]

KeyManagerWorks是一个最终类,它根本没有公共构造函数。getKeyManager方法也是最终的。我已经有了一个KeyManager[],所以我想破解这个KeyManagerWorks来返回我自己的数组自己的KeyManager并将其提供给构建器。

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

共有2个答案

谭越
2023-03-14

在@tgdavies的提示下,我能够完成我想要的事情。非常感谢。

因此,我创建了一个< code > KeyManagerFactoryWrapper ,其中包含一个名为< code > KeyManagerFactorySpi wrapper 的自定义< code > KeyManagerFactorySpi 。

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);
陈斌
2023-03-14

您可以这样做。(您可以对私有字段使用setAccesable(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());
    }
}
 类似资料:
  • 我是Java的初学者。我正在学习最终变量,并尝试了这段代码。 然而,Eclipse给了我一个错误。 我做错了什么?如何将所有对象的最终变量设置为静态?

  • 问题内容: 在Objective-C实例数据可以是,或。例如: 在Swift参考中,我还没有提到访问修饰符。是否有可能限制Swift中数据的可见性? 问题答案: 从 Swift 3.0.1开始 ,共有 4级访问权限 ,从最高(最低限制)到最低(最高限制)进行描述。 1. 和 允许在定义模块(目标)之外使用实体。指定框架的公共接口时,通常使用或访问。 但是, 访问权限仅适用于类和类成员,它与访问不同

  • JAVA访问修饰符的可访问性 公众 在 同一班级 同一套餐 子类 宇宙/其他软件包 我在互联网上寻找这些问题的答案,因为我有多个答案。一个视频说未声明的访问修饰符是公共的,而我看到另一个书面来源说未声明的访问修饰符在子类和其他包中没有限制。试图确认哪个是真的。

  • 问题内容: 我知道这不仅适用于Java,而且适用于许多语言,但这是我最熟悉的语言。 我了解修饰符的作用以及如何使用它们。我只想知道,为什么我们需要它们?为什么每个对象都无法访问,无论是否需要访问? 问题答案: 当您必须维护更大的项目时,原因变得更加明显。当方法或变量是公共的时,对它进行更改时必须小心,因为您永远不知道代码库的哪些部分依赖于它的确切行为。 但是,当变量或方法是私有的时,您会知道该变量

  • 主要内容:私有(Private)成员,实例,保护(Protected)成员,实例,公共(Public)成员,实例,作用域保护,实例Scala 访问修饰符基本和Java的一样,分别有:private,protected,public。 如果没有指定访问修饰符,默认情况下,Scala 对象的访问级别都是 public。 Scala 中的 private 限定符,比 Java 更严格,在嵌套类情况下,外层类甚至不能访问被嵌套类的私有成员。 私有(Private)成员 用 private 关键字修饰,带

  • 根据留档(http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html)的第二个表,没有标识符的成员对子类不可见。 但是,当我运行下面的示例代码时,“1”(b的内容)被打印出来! 如果没有访问修饰符的成员不能从子类访问,那么为什么在本例中打印它 它应该抛出一个错误,就像在私有访问修饰符中一样,不是吗?