VoidWhisperer
VoidWhisperer

Reputation: 73

Java - Instantiation

I'm trying to create a new class of something I'm not entirely sure of the class type. This could be better explained with my code:

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;
    }
}

and for anyone wondering what TCPPacket is:

package vc.voidwhisperer.proxy.packet;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

public class TCPPacket {
    public TCPPacket()
    {

    }
    public byte id = 0;
    public void writePacketData(DataOutputStream os) throws IOException
    {

    }
    public void readPacketData(DataInputStream is) throws IOException
    {

    }
    public void setId(byte id)
    {

    }
}

As you can see I'm trying to instaniate a new object that I can't be entirely sure of what the class type is. However, it's spitting out this exception:

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)

Upvotes: 0

Views: 2541

Answers (2)

Christopher Schultz
Christopher Schultz

Reputation: 20837

You are trying to instantiate a non-static inner Class from within a static method. Creating a new HandshakePacket object requires a surrounding Packet object as it's parent, and you aren't providing one.

So, either make HandshakePacket a static inner class, make getNewPacket a non-static method, or create a new Packet object to use as a parent for your new HandshakePacket object.

Upvotes: 2

Mike Samuel
Mike Samuel

Reputation: 120496

Reflection is overkill for this.

Just do

switch (i) {
  case 0: return new KeepAlivePacket();
  case 1: return new LoginRequestPacket();
  case 2: return new HandshakePacket();
  default: throw new IllegalArgumentException();
}

and ideally replace i with an enum.

That will get you the advantages of static type and signature checks making your code more maintainable, and avoids all the reflective guff that masks exceptions.

Upvotes: 2

Related Questions