I have a class called Packet and a class called PacketClientConnecting witch extends it. The instances of PacketClientConnecting and other packets are stored in ArrayList<Packet>.
I want to have access to id value in static and non-static ways eg PacketClientConnecting.getStaticId() or packetArrayList.get(5).getId().
How can i do this without overriding two functions in every class?
I don't think there's a really smooth way of doing this, but one can achieve what you want by using reflection (only once: in the base class):
class Packet {
public static int getStaticId() {
return 1;
}
// This method is virtual and will be inherited without change
public int getId() {
try {
// Find and invoke the static method corresponding
// to the run-time instance
Method getStaticId = this.getClass().getMethod("getStaticId");
return (Integer) getStaticId.invoke(null);
// Catch three reflection-related exceptions at once, if you are on Java 7+,
// use multi-catch or just ReflectiveOperationException
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
Now in the subclass all you need is define getStaticId():
class PacketClientConnecting extends Packet {
public static int getStaticId() {
return 2;
}
}
Let's test it:
class Main {
public static void main(String[] args) {
// Both print 1
System.out.println(Packet.getStaticId());
System.out.println(new Packet().getId());
// Both print 2
System.out.println(PacketClientConnecting.getStaticId());
System.out.println(new PacketClientConnecting().getId());
}
}
If you want to avoid the overhead of calling reflective operations every time you call getId(), you can use a field in the base class to cache the id:
class Packet {
public static int getStaticId() {
return 1;
}
private final int id = computeId();
public int getId() {
return id;
}
// This method runs once per instance created
private int computeId() {
try {
Method getStaticId = this.getClass().getMethod("getStaticId");
return (Integer) getStaticId.invoke(null);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
Related
I was trying to write the following piece of code, but the error happened on line return super.getAge("Jack");
It showed "The method getAge() is undefined for the type Object". I guess the "super" keyword is not identified here.
Does anyone have any suggestions that how to fix this error? Thanks so much!
public class Parent {
public int getAge(String name) {
System.out.println("Get the age of the parent.");
return 40;
}
}
public class Child extends Parent {
#Override
public int getAge(String name) {
Future<Integer> ageFuture = null;
#Qualifier("XXX")
private ExecutorService executorService;
try {
ageFuture = executorService.submit(new Callable<Integer>() {
public int call() throws Exception {
return super.getAge("Jack");
}
});
} catch (Exception e) {
logger.error(" ", e);
}
return 10;
}
}
Try Parent.super.getAge("jack"), though I don't think that will work.
If not, then your only option is to make a bridge method:
public class Child extends Parent {
private int superGetAge(String name) {
return super.getAge(name);
}
#Override
public int getAge(String name) {
.... return superGetAge("jack");
}
}
Because you are using new Callable() which is instantiating a new class then super.getAge("jack") is referring to a non-existant method.
Instead switch to lambda definition which can reference super.getAge("Jack") directly:
Callable<Integer> call = () -> super.getAge("Jack");
try {
ageFuture = executorService.submit(call);
}
// etc...
or shorter:
ageFuture = executorService.submit(() -> super.getAge("Jack"));
Youre defining a new class on-the-fly with "new Callable {...} "
That class is inherited from Object.
You could try defining the Parent getAge() as a static method and call it with
Parent.getAge("Jack");
Hi
In the game Minecraft you have to send data between the client and the server in order to sync stuff, one of the things that need to be synced in particular circumstances is TileEntities with a render. The data is stored on the server and sent to the client which is thereafter used for render.
You create a class that contains the data that needs to be synced and attach it to a channel creation API called "SimpleImpl". My Network object and a Message Object:
public class IntercraftPacketHandler
{
private static int index = 1;
private static final ResourceLocation CHANNEL_NAME = new ResourceLocation(Reference.MODID,"network");
private static final String PROTOCOL_VERSION = new ResourceLocation(Reference.MODID,"1").toString();
public static SimpleChannel getNetworkChannel()
{
final SimpleChannel channel = NetworkRegistry.ChannelBuilder.named(CHANNEL_NAME)
.clientAcceptedVersions(version -> true)
.serverAcceptedVersions(version -> true)
.networkProtocolVersion(() -> PROTOCOL_VERSION)
.simpleChannel();
// Sync Capability Identity Hidden data message.
channel.messageBuilder(MessageIdentityHidden.class,index)
.encoder(MessageIdentityHidden::encode)
.decoder(MessageIdentityHidden::decode)
.consumer(MessageIdentityHidden::handle)
.add(); index++;
// Send TreeTapTileEntity data to client.
channel.messageBuilder(MessageTreeTap.class,index)
.encoder(MessageTreeTap::encode)
.decoder(MessageTreeTap::decode)
.consumer(MessageTreeTap::handle)
.add(); index++;
// Send ChunkLoaderTileEntity data to client.
channel.messageBuilder(MessageChunkLoader.class,index)
.encoder(MessageChunkLoader::encode)
.decoder(MessageChunkLoader::decode)
.consumer(MessageChunkLoader::handle)
.add(); index++;
return channel;
}
}
public class MessageChunkLoader
{
private BlockPos pos;
private boolean canLoad;
public MessageChunkLoader(BlockPos pos,boolean canLoad)
{
this.pos = pos;
this.canLoad = canLoad;
}
public void handle(Supplier<NetworkEvent.Context> ctx)
{
ctx.get().enqueueWork(() -> {
try {
ChunkLoaderBaseTileEntity tile = (ChunkLoaderBaseTileEntity) Minecraft.getInstance().world.getTileEntity(pos);
tile.canLoad = canLoad;
} catch (NullPointerException err) {
System.out.println(String.format("Could not find ChunkLoaderTileEntity at %s %s %s!",pos.getX(),pos.getY(),pos.getZ()));
}
});
}
public static void encode(MessageChunkLoader message, PacketBuffer buffer)
{
buffer.writeBlockPos(message.pos);
buffer.writeBoolean(message.canLoad);
}
public static MessageChunkLoader decode(final PacketBuffer buffer)
{
return new MessageChunkLoader(buffer.readBlockPos(),buffer.readBoolean());
}
}
I then initialize it in my main mod class used by objects in my mod project.
#Mod(Reference.MODID)
public class IntercraftCore
{
public static final SimpleChannel NETWORK = IntercraftPacketHandler.getNetworkChannel();
...
The problem and this post's question; right now I create a new message class from the formula I follow in MessageChunkLoader (public static encode & decode method and a handle method). I would like to create a more generic class for creating message classes for TileEntities, but I'm having problems with that. Here's the current class:
public abstract class MessageTileEntity<T extends TileEntity>
{
protected final BlockPos pos;
protected final Class<T> clazz;
public MessageTileEntity(BlockPos pos, Class<T> clazz)
{
this.pos = pos;
this.clazz = clazz;
}
public abstract void handle(Supplier<NetworkEvent.Context> ctx);
protected T getTileEntity()
{
try {
return clazz.cast(Minecraft.getInstance().world.getTileEntity(pos));
} catch (NullPointerException e) {
System.out.println(String.format("Could not find %s at [%d %d %d]!",clazz.getSimpleName(),pos.getX(),pos.getY(),pos.getZ()));
throw e;
} catch (ClassCastException e) {
System.out.println(String.format("TileEntity at [%d %d %d] is not %s!",pos.getX(),pos.getY(),pos.getZ(),clazz.getSimpleName()));
throw e;
}
}
public static void encode(MessageTileEntity message, PacketBuffer buffer)
{
}
public static MessageTileEntity decode(final PacketBuffer buffer)
{
return null;
}
}
The main problem is I lack the proper Java skills to make it like I want it to function. The method handle is easy as it's non-static and needs to be custom to every TileEntity message, but the methods encode and decode which needs to be static gives me problems. I have no idea what I'm trying to achieve is possible, asking won't hurt. Maybe the solution is easier than I think.
I was trying to review some of the Java language using a spark chart I had once bought. Regarding the use of anonymous inner classes they give this example :
Dice rollDice() {
return new Dice() {
int number = (int)( Math.random() * 6 ) + 1;
};
}
Problem is, I do not see how this would work, and can not get the compiler to accept it as a method within another class. The compiler complains about each reference to Dice "symbol can not be found."
Am I not understanding their example correctly or is this completely invalid code? Thanks in advance!
p.s. if this is working code, could someone provide me with an example of how it can be used?
Edit: I have found something that finally makes sense
The syntax for an anonymous inner class is shown below
new SuperClassName/InterfaceName() {
// Implement or override methods in superclass or interface
// Other methods if necessary
}
This above code is passed to a method that takes an instance of Superclass or completely implements the Interface. For instance, a method that has an EventHandlerparameter and we have not already defined a class that implements the handle(ActionEvent e) method.
enlargeButton.setOnAction(
new EventHandler<ActionEvent>() {
public void handle(ActionEvent e) {
circlePane.enlarge();
}
});
In this way, it will truly be anonymous. I think the example given in Java's own tutorial to be very poor.
It looks like you've mostly answered your own question and you will probably want to go through some full tutorial or documentation to understand things fully, but here are some answers to your immediate questions.
Your first sample code wont compile until you have a Dice class or interface you can extend. So as an example you can get this code to compile:
class Dicey {
interface Dice {
}
Dice rollDice() {
return new Dice() {
int number = (int) (Math.random() * 6) + 1;
};
}
public static void main(String... none) {
Dice dice = new Dicey().rollDice();
// dice.number; <-- not available
}
}
Now you can do this, but as you suspect this is not a very useful things to do (for a few reasons) but the biggest problem is that after you create this anonymous instance there isn't really a way to get to the .number member.
More usually you would have an anonymous subclass implement some methods on the interface, so that you can actually do something with it. So for example
class HelloAnonymous {
interface Hello {
String say();
}
Hello hello(String world) {
return new Hello() {
public String say() {
return world;
}
};
}
public static void main(String... none) {
System.out.println(new HelloAnonymous().hello("world").say());
// prints 'world'
}
}
gives you a way of making fantastically useful Hello objects that can say something. Having said all this, writing anonymous inner classes is fairly old school because functional interfaces now largely replace the need for them. So in this example you could have:
class HelloAnonymous {
#FunctionalInterface
interface Hello {
String say();
}
// old school
Hello hello(String world) {
return new Hello() {
public String say() {
return world;
}
};
}
// with lambda notation
Hello alsoHello(String world) {
return () -> {
return world;
};
}
public static void main(String... none) {
System.out.println(new HelloAnonymous().hello("world").say());
System.out.println(new HelloAnonymous().alsoHello("world").say());
}
}
since I don't know about 'Dice' class I cannot write same method but I try some thing similar to that. It compile and work can access 'number' variable by using reflection. My opinion is it is not very useful. Following is my code:
public class TestClass {
public static void main(String a[]){
TestClass aClass = rollDice();
try {
System.out.println("value of number : " + aClass.getClass().getDeclaredField("number").getInt(aClass));
}
catch (NoSuchFieldException e) {
e.printStackTrace();
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
}
static TestClass rollDice() {
return new TestClass() {
int number = (int) (Math.random() * 6) + 1;
};
}
}
That example is extremely broken. Throw that source away. Try this:
import java.util.Random;
public class DieFactory {
interface Die { int roll(); }
static Die create(long seed) {
Random random = new Random(seed);
return new Die() {
#Override
public int roll() {
return random.nextInt(6) + 1;
}
};
}
// Now you can roll 2 dice pretty easily.
public static void main(String [] args) {
DieFactory.Die die1 = DieFactory.create(42);
DieFactory.Die die2 = DieFactory.create(24);
for (int i = 0; i < 40; i++) {
System.out.println(die1.roll() + die2.roll());
}
}
}
Incidentally, the word "dice" is plural for the singular "die."
I have this class:
public class MyClass{
private Test test;
public class Test{
int num;
String color;
public Test(int num, String color){
this.num = num;
this.color = color;
}
}
public MyClass(){
}
public void setNum(int number){
test.num = number;
}
public void setColor(String color){
test.color = color;
}
public Test getTest(){
return test;
}
}
I am setting the values from another class and at the end I call the method getTest:
MyClass myclass = new MyClass();
.
.
.
Test test1 = myclass.getTest();
I want to Iterate the object test1 to get the values. Is that possible? Do I have to implement hasNext() method inside the class MyClass? If yes, how can I do it?
You question has already been asked and answered.
Basic idea - you need to use reflection API . E.g construction test.getClass().getDeclaredFields();
Note: you will not create iterator this way, but you will be able to iterate through class fields. That slightly different things.
You want this?
public static void main(String[] args) {
MyClass myclass = new MyClass();
Test test1 = myclass.getTest();
//you need modify private Test test = new Test(1, "hahs");
//import java.lang.reflect.Field;
Field[] fields = test1.getClass().getDeclaredFields();
for (int j = 0; j < fields.length-1; j++) {
fields[j].setAccessible(true);
try {
System.out.println(fields[j].get(test1));
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//output
//1
//hahs
}
You will have to use reflection in order to iterate through the members of the test class. You will have to import java.lang.reflect.* and call Class.forName("test1) to get a Class object, and call the getDeclaredFields method of the Class object to get an array of Field objects. The Field object has get and set methods that get or set the value of the field.
Would I do something like this?
Assert.assertTrue(value = int n);
Also, if I had a method such as:
public int get(){
return count;
}
What kind of a test case would I write for it? Would I write a test case testing if the return is an integer?
Regrading your first question - the return type is an int (so you don't need to verify that).
Regarding your second question, if it's just a getter, there's no need to write test for it.
Generally, unit test helps you to test bussiness logic and that a certain behavior of a building block of your app works.
If we'll take the count for example, you would probably want to build up a test case with actions that affects the count in a specific way and then assert on it's expected value.
You can look here for a nice tutorial on Unit Tests in Java.
Class for testing purpose:
public class Item {
private int number;
public Item(int number) {
this.number = number;
}
public int getNumber() {
return number;
}
}
Your test cases could be:
import static org.junit.Assert.*;
public class Test {
#org.junit.Test
public void testCase1() {
Item item = new Item(1);
assertEquals(1, item.getNumber());
}
#org.junit.Test
public void testCase2() {
Item item = new Item(2);
assertEquals(2, item.getNumber());
}
}
You can verify your business logic via assertEquals method.
How would I write a test case in Java to test that the input is an int?
Assuming your concern is someone could change input type of a method.
public final void testSet() {
try {
MyClass.class.getDeclaredMethod("set", new Class[] { Integer.TYPE });
} catch (NoSuchMethodException e) {
Assert.assertFalse(true);
} catch (SecurityException e) {
e.printStackTrace();
}
}
Would I write a test case testing if the return is an integer?
Assuming your concern is someone could change return type of a method. By the way you are returning int in your example so I have used Integer.TYPE, if you want to check for Integer then use Integer.class
public final void testGet() {
try {
java.lang.reflect.Method m = MyClass.class.getDeclaredMethod("get", null);
Assert.assertTrue(m.getReturnType() == Integer.TYPE);
} catch (NoSuchMethodException | SecurityException e) {
e.printStackTrace();
}
}