java - 创建泛型类成员的实例:Class.newInstance() 抛出异常
问题描述
我想创建一个通用类来存储临时对象池(例如 2D 矢量 Vec2d ),这样我就不必在模拟期间动态分配它们。基于这些答案[1] [2]我得出了这个解决方案:
import java.lang.reflect.Array;
class TempPool<T>{
T[] objs;
public TempPool(Class<T> c, int n) {
T[] a = (T[])Array.newInstance(c, n); // initialize the array
try{ // Compiler forces me to use try fo handling
for(int i=0; i<n; i++) a[i]=(T)c.newInstance(); // initialize fields in the array
}catch(Exception e){
System.out.println("Exception thrown :" + e +" in TempPool()" );
}
objs = a;
}
T borrow( ){ return objs[icur++]; };
void repay(T o){
if( o != objs[icur] ) objs[-1]=null; // Throws exeption
}else{ icur--; }
}
但是当我尝试使用
class Vec2d{ double x,y; }
tmpVec2d = new TempPool (Vec2d.class,10); // tried both
//tmpVec2d = new TempPool<Vec2d>(Vec2d.class,10); // tried both
它抛出异常
Exception thrown :java.lang.InstantiationException: Boulders_rigid$Vec2d in TempPool()
解决方案
内部课程并不像您认为的那样运作。
内部类如下所示:
class Outer /* must be a class; not an interface */ {
class Inner /* A class (not an interface), AND, not static {
}
}
内部类有一个秘密的、不可见的 final 字段,如下所示:
private final Outer magicThis;
那不可能null
。每个Inner
具有的构造函数都有第一个参数Outer magicThis
,但这个参数也是隐藏的。要传递它,您可以使用这种奇怪的语法:
outerInstance.new Inner();
并且,至关重要的是,这使它变得“神奇” ,从某种意义上说,你不知道它是这样工作Outer.this
的as outerInstance:在那些上下文中,并且只有在那些上下文中,才有效。Outer
Outer.this
new Inner()
既然你知道了这一切,那么你就会明白newInstance()
在非静态内部类上调用是行不通的:这需要一个无参数的构造函数,而且没有一个:所有构造函数都有那个秘密的、不可见的Outer magicThis
参数。
您可以使用该javap
工具观察所有这些。
解决方案很简单:将您的内部类标记为static
. 事实上,继续将所有内部类标记为静态。只有当你真的知道你在做什么并且你绝对确定你真的想要它时才创建非静态内部类 - 神奇的东西往往会让人们失望,并且很容易对代码做出错误的假设。例如,外部的秘密参考?这真的会让你陷入垃圾收集(它会阻止收集外部实例!)。
请注意,您的代码质量非常糟糕。需要研究的几件事:
正确的“我不知道该怎么做”异常处理程序永远不会只记录它并忘记它,并且 System.out 不是适当的记录位置。只是
e
扔掉几乎所有相关信息——尤其是你不想扔掉的原因。我不知道异常块的正确处理程序始终是:throw new RuntimeException("Unhandled", e);
. 这简短、简单,不会导致代码继续在未知状态下运行,并保留所有信息。解决这个问题。不要
newInstance()
去上课;它已被弃用。它有疯狂的异常行为。你想要c.getConstructor().newInstance()
。objs[-1] = null
当然抛出;没有-1索引。想必你想要objs[icur] = null
?或者也许objs[objs.length - 1] = null;
?我不确定repay
要完成什么。
推荐阅读
- python - 从python中的span类获取数据
- sql - Spark中带有WHERE子句的嵌套SELECT
- unicode - UnicodeDecodeError:“utf-8”编解码器无法解码 Visual Studio Code 中的字节
- mysql - 确保不同表中的 2 列逐行相同 MySQL
- python - Dill/Pickle:转储自定义类对象
- maven - jfrog命令行如何设置Maven神器组和版本?
- sql - 如何在 sas 企业指南日志中获取数据集大小
- mysql - 添加一个新的选择字段
- css - less css 避免全局变量
- ios - 尝试从 UIViewController 到 Weather API 的序列数据