Java 如何重用类实例化的逻辑并绕过IllegaAccessException?
目标:创建一个包含一些反射代码的util类,特别是创建新类实例的代码。这段代码不是很简单,所以我想把它保存在一个util函数中,这样我就可以多次重用它 方法/想法:创建ClassUtil,该函数将返回创建新类实例的lambda。我将在MyClassFactory中执行该lambda,我知道该类可以创建MyClassOne的新实例,因为它将在同一个包中,并且默认构造函数是package private access修饰符,因此ClassUtil无法创建该类的实例,但因为我在一个类中执行lambda,所以所有这些都应该是好的 错误: java.lang.IllegalAccessException:com.util.ClassUtil类无法使用修饰符访问com.somepackage.MyClassOne类的成员 问题:如何让Java运行时认为是MyClassFactory在尝试实例化 统一建模语言: 代码: 包com.somepackage 导入com.util.ClassUtil; 公共类MyClassFactory{ 公共MyClass创建MyClass{ 字符串implClassFQN=; 返回MyClass ClassUtil.createClassInstance.applyimplClassFQN; } } 包com.util; 导入java.lang.reflect.InvocationTargetException; 导入java.util.function.function; 公共类ClassUtil{ /** *@return给定类的完全限定名,返回该类的新实例 */ 公共静态函数createClassInstance{ 返回classFQN->{ 试一试{ 返回Class.forNameclassFQN.getDeclaredConstructor.newInstance; }捕获类NotFounde异常{ 抛出未找到属性文件中指定的新RuntimeExceptionImpl类,e; }捕获无此方法异常{ 未找到抛出新RuntimeExceptionDefault构造函数,e; }捕获非法访问异常|实例化异常|调用目标异常e{ 抛出新的RuntimeExceptionOne; } }; } } 解决方法/新方法:有人知道我如何能够采取不同的方法来实现相同的目标吗Java 如何重用类实例化的逻辑并绕过IllegaAccessException?,java,lambda,reflection,Java,Lambda,Reflection,目标:创建一个包含一些反射代码的util类,特别是创建新类实例的代码。这段代码不是很简单,所以我想把它保存在一个util函数中,这样我就可以多次重用它 方法/想法:创建ClassUtil,该函数将返回创建新类实例的lambda。我将在MyClassFactory中执行该lambda,我知道该类可以创建MyClassOne的新实例,因为它将在同一个包中,并且默认构造函数是package private access修饰符,因此ClassUtil无法创建该类的实例,但因为我在一个类中执行lambda
注意:如果我将ClassUtil中的代码放入MyClassFactory,它可以正常工作,但我希望它可以重用。尝试通过以下方式设置可访问的构造函数:
尝试设置可通过以下方式访问的构造函数:
从字面上回答您的问题,假设调用方对所调用的方法有足够的信任,则有一个方法可以传递给另一个方法来执行操作,而不需要访问重写 与访问覆盖不同的是,即使在受限环境中,如安装了安全管理器,或访问将跨越模块边界时,这也可以工作。此外,类查找就像在调用方的代码中发生一样执行,这在两个包属于不同的类装入器时可能是相关的
package com.somepackage;
import com.util.ClassUtil;
import java.lang.invoke.MethodHandles;
public class MyClassFactory {
public static void main(String[] args) {
MyClass obj = new MyClassFactory().createMyClass();
System.out.println("created "+obj);
}
public MyClass createMyClass() {
String implClassFQN = MyClassFactory.class.getName()+"$MyClass";
return (MyClass)ClassUtil.createClassInstance(MethodHandles.lookup())
.apply(implClassFQN);
}
private static class MyClass { // normally inaccessible by com.util.ClassUtil
}
}
从字面上回答您的问题,假设调用方对所调用的方法有足够的信任,则有一个方法可以传递给另一个方法来执行操作,而不需要访问重写 与访问覆盖不同的是,即使在受限环境中,如安装了安全管理器,或访问将跨越模块边界时,这也可以工作。此外,类查找就像在调用方的代码中发生一样执行,这在两个包属于不同的类装入器时可能是相关的
package com.somepackage;
import com.util.ClassUtil;
import java.lang.invoke.MethodHandles;
public class MyClassFactory {
public static void main(String[] args) {
MyClass obj = new MyClassFactory().createMyClass();
System.out.println("created "+obj);
}
public MyClass createMyClass() {
String implClassFQN = MyClassFactory.class.getName()+"$MyClass";
return (MyClass)ClassUtil.createClassInstance(MethodHandles.lookup())
.apply(implClassFQN);
}
private static class MyClass { // normally inaccessible by com.util.ClassUtil
}
}
我太过沉迷于欺骗Java了——它认为是另一个类进行了实例化,我甚至没有想到像您的@PSandro这样的简单解决方案来忽略访问修饰符:非常感谢您这么快的回答!我太过沉迷于欺骗Java了——它认为是另一个类进行了实例化,我甚至没有想到像您的@PSandro这样的简单解决方案来忽略访问修饰符:非常感谢您这么快的回答!谢谢@Holger,MethodHandles是我以前没有见过的东西,尽管它已经存在了很长一段时间。我无法通过搜索web找到有用的资源,大多数人只是将其与reflection或lambdametafactory进行比较,并做了一些利弊分析,但没有说明何时使用哪个、什么用例最适合每个人。显然,在功能上存在重叠,因此必须为每种功能都提供一个最佳方案。我会找一本新书,等我有时间的时候再做我自己的分析。如果您有任何建议,我洗耳恭听:这解决了问题标题中的问题以及问题正文中提出的在线问题。>如何让Java运行时认为是MyClassFactory在尝试实例化?所以我接受了这个。谢谢@Holger,MethodHandles是我以前没见过的东西,尽管它已经存在了很长一段时间了。我在网上找不到有用的资源,
他们中的大多数只是将它与反射或lambdametafactory进行比较,并做一些利弊分析,但没有说明何时使用哪个,什么用例最适合每种情况。显然,在功能上存在重叠,因此必须为每种功能都提供一个最佳方案。我会找一本新书,等我有时间的时候再做我自己的分析。如果您有任何建议,我洗耳恭听:这解决了问题标题中的问题以及问题正文中提出的在线问题。>如何让Java运行时认为是MyClassFactory在尝试实例化?所以接受这个。
package com.util;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.function.Function;
public class ClassUtil {
/**
* @return a new instance of the class given the class fully qualified name
*/
public static Function<String, Object>
createClassInstance(MethodHandles.Lookup context) {
return name -> {
try {
return context.findConstructor(context.findClass(name),
MethodType.methodType(void.class)).invoke();
} catch(ClassNotFoundException e) {
throw new RuntimeException(
"Impl class specified in properties file not found", e);
} catch(NoSuchMethodException e) {
throw new RuntimeException("Default constructor not found", e);
} catch(RuntimeException | Error e) {
throw e;
} catch(Throwable e) {
throw new RuntimeException(e);
}
};
}
}