Java实例化

Java实例化,java,instantiation,instantiationexception,Java,Instantiation,Instantiationexception,我正在尝试创建一个新类,但我不完全确定该类的类型。我的代码可以更好地解释这一点: private static Class[] Packets = new Class[] { KeepAlivePacket.class, // 0x00 LoginRequestPacket.class, // 0x01 HandshakePacket.class, // 0x02

我正在尝试创建一个新类,但我不完全确定该类的类型。我的代码可以更好地解释这一点:

private static Class[] Packets = new Class[]
            {
                KeepAlivePacket.class, // 0x00
                LoginRequestPacket.class, // 0x01
                HandshakePacket.class, // 0x02
                    }
.......

class HandshakePacket extends TCPPacket
{
    public HandshakePacket()
    {

    }
    byte protocolVersion;
    String username;
    String host;
    int port;
    @Override
    public void writePacketData(DataOutputStream os) throws IOException {
        os.write(id);
        os.writeByte(protocolVersion);
        writeString(os, username);
        writeString(os, host);
        os.writeInt(port);
    }
    @Override
    public void readPacketData(DataInputStream is) throws IOException {
        protocolVersion = is.readByte();
        username = readString(is,16);
        host = readString(is,16);
        port = is.readInt();
    }
    @Override
    public void setId(byte id)
    {
        this.id = id;
    }
}

.......
    public static TCPPacket getNewPacket(int i)
    {
    try
    {
        Class var1 = (Class)Packets[i];
        return var1 == null ? null : (TCPPacket)var1.newInstance(); <-- error on this line
    }
    catch (Exception var2)
    {
        var2.printStackTrace();
        System.out.println("Skipping packet with id " + i);
        return null;
    }
}
如您所见,我试图实例化一个新对象,但我不能完全确定类类型是什么。然而,它却抛出了一个例外:

java.lang.InstantiationException: vc.voidwhisperer.proxy.packet.Packet$HandshakePacket
at java.lang.Class.newInstance0(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at vc.voidwhisperer.proxy.packet.Packet.getNewPacket(Packet.java:2509)
at vc.voidwhisperer.proxy.UserConnection.run(UserConnection.java:52)

对于这一点,反思是过分的

照办

switch (i) {
  case 0: return new KeepAlivePacket();
  case 1: return new LoginRequestPacket();
  case 2: return new HandshakePacket();
  default: throw new IllegalArgumentException();
}
理想情况下,用枚举替换
i


这将使您获得静态类型和签名检查的优势,使您的代码更易于维护,并避免所有掩盖异常的反射废话。

反射在这方面是过分的

照办

switch (i) {
  case 0: return new KeepAlivePacket();
  case 1: return new LoginRequestPacket();
  case 2: return new HandshakePacket();
  default: throw new IllegalArgumentException();
}
理想情况下,用枚举替换
i


这将使您获得静态类型和签名检查的优势,使代码更易于维护,并避免所有掩盖异常的反射性废话。

您正试图从静态方法中实例化非静态内部类。创建一个新的
HandshakePacket
对象需要一个周围的数据包对象作为其父对象,而您并没有提供它


因此,要么使
HandshakePacket
成为一个静态内部类,要么使
getNewPacket
成为一个非静态方法,要么创建一个新的Packet对象作为新的
HandshakePacket
对象的父对象。

您试图从静态方法中实例化一个非静态内部类。创建一个新的
HandshakePacket
对象需要一个周围的数据包对象作为其父对象,而您并没有提供它



因此,要么使
HandshakePacket
成为一个静态内部类,要么使
getNewPacket
成为一个非静态方法,要么创建一个新的Packet对象作为新的
HandshakePacket
对象的父对象。

实例化异常包装了通常在它之后打印的真正异常。你能提供实际的例外情况吗?它还表示调用Packet.HandshakePacket的构造函数时发生异常。您能否提供导致异常的类的源代码,并告诉use它发生在哪一行?顺便问一下,
setId
没有设置
id
字段有什么原因吗?包括
HandshakePacket
中与您的问题相关的代码,包括其构造函数。我建议复制/粘贴代码(不要在问题中手动键入)。@PeterLawrey我认为TCPPacket的内容是为了空间而隐藏的…@PeterLawrey我没有选择,这是从其他人的协议中获取数据包:/InstantiationException包装了真正的异常,通常在它之后打印。你能提供实际的例外情况吗?它还表示调用Packet.HandshakePacket的构造函数时发生异常。您能否提供导致异常的类的源代码,并告诉use它发生在哪一行?顺便问一下,
setId
没有设置
id
字段有什么原因吗?包括
HandshakePacket
中与您的问题相关的代码,包括其构造函数。我建议复制/粘贴代码(不要在问题中手动输入)。@PeterLawrey我认为TCPPacket的内容是为了空间而隐藏的…@PeterLawrey我没有选择,这是从其他人的协议中获取数据包:/大约有200个数据包。这并不过分:/Meh,用代码换取内存是一个长期争论的问题。如果要从文件中读入配置,则可以更好地论证使用基于数据的分派而不是基于代码的分派。@Whitterer,对于大型手动编码阵列,交换机方法是成功的。密集int开关的每一个大小写开销为零,因为它只编译为一个边界检查和
jsr
指令。返回无效构造函数调用结果的每个case语句对
new
指令分别占用3个字节,返回1个字节。设置200个元素数组的静态初始值设定项的大小要大得多,因为每个aastore需要3条其他指令来设置堆栈:
a=new Class[]{x,y,z}
实际上将desugas转换为
a=new Class[3];a[0]=x;a[1]=y;a[2]=z@voidWhisper,从运行时角度看,switch语句和CTOR可以通过JIT内联,但反射使用不会每次都产生运行时开销和不可预测的分支。大约有200个数据包。这并不过分:/Meh,用代码换取内存是一个长期争论的问题。如果要从文件中读入配置,则可以更好地论证使用基于数据的分派而不是基于代码的分派。@Whitterer,对于大型手动编码阵列,交换机方法是成功的。密集int开关的每一个大小写开销为零,因为它只编译为一个边界检查和
jsr
指令。返回无效构造函数调用结果的每个case语句对
new
指令分别占用3个字节,返回1个字节。设置200个元素数组的静态初始值设定项的大小要大得多,因为每个aastore需要3条其他指令来设置堆栈:
a=new Class[]{x,y,z}
实际上将desugas转换为
a=new Class[3];a[0]=x;a[1]=y;a[2]=z@voidWhisper,从运行时角度来看,switch语句和ctor可以由JIT内联,但反射使用不会每次都产生运行时开销和不可预测的分支。@voidWhisper,如果要反射调用内部类构造函数,您需要将外部实例作为第一个参数传递,因为
outerInstance.new NonStaticInnerClass()
desugas到
new OuterClass$NonStaticInnerClass(outerInstance)
new NonStaticInnerClass()
实际上是
this.new NonStaticInnerClass()
所以desugas到
new OuterClass$NonStaticInnerClass(这个)
Class.newInstance()
不起作用。您需要使用.Yo