Java – 模板中Byte,Integer,Long等的原始对应部分

背景

我正在尝试实现一个小模板,即generics类,这将允许我实现如下的传递引用function。

public static class Ref { T value; public Ref(T InitValue) { this.set(InitValue); } public void set(T Value) { this.value = Value; } public T get() { return this.value; } } 

所以,我可以定义一个函数,它接受一个’Ref’,其值可以实际改变,例如

 public static void function(Ref x) { x.set((byte)0x7E); } 

要通过引用传递的变量的初始化看起来不那么优雅。

 Ref to_be_changed = new Ref((byte)0); ... function(to_be_changed); ... Byte result = to_be_changed.get() 

问题

Java有没有办法做得更好? 构造函数可以根据与作为模板类型传递的包装类型相关的基元类型直接初始化’0’吗? 就是这样的

  ... public Ref() { this.value = (T.relatedPrimitiveClass())0; } ... 

其中Integer.relatedPrimitiveClass()将传递int ; Byte.relatedPrimitiveClass()传递byte

首先,最重要的是要理解javagenerics不是模板。 generics是在类型上参数化的类/接口。 我建议从oracle阅读generics教程: https : //docs.oracle.com/javase/tutorial/java/generics/types.html

可以使用reflection来获取Ref类的参数化类型T,并使用它来确定默认construtor的初始值,但我不建议这样做。

您可以为需要默认构造函数(例如基元的对象版本)的类型创建子类,而不是reflection:

 public static class ByteRef extends Ref { public ByteRef() { super((byte)0); } public ByteRef(byte value) { super(value); } // I'm not sure, if I like this one :-) public void set(int value) { super.set((byte)value); } } 

您也可以向Ref类添加新方法,而不是子类化:

 public static class Ref { T value; public Ref(T initValue) { this.set(initValue); } public void set(T Value) { this.value = Value; } public T get() { return this.value; } public static Ref createByteRef() { return new Ref((byte)0); } public static Ref createByteRef(byte value) { return new Ref(value); } } 

或者你可以创建单独的工厂类:public class Refs {public static Ref createByteRef(){return new Ref((byte)0); }

  public static Ref createByteRef(byte value) { return new Ref(value); } } 

最后一个选项是使用reflection来获取参数化类型。 我个人不会使用这个解决方案,因为原始类的数量是有限的,您可以选择使用子类创建更多更简洁的接口

 public abstract static class PrimitiveNumberRef extends Ref { private Class type; public PrimitiveNumberRef() { // This requires default constructor for Ref class type = getGenericType(getClass()); super.set((T) getInitialValue(type)); } @Override public void set(T value) { if (value == null) { throw new IllegalArgumentException( "Null value is not allowed for PrimitiveNumerRef type: " + type); } if (!type.isInstance(value)) { throw new IllegalArgumentException("Unsupported value type: " + value.getClass()); } super.set(value); } @SuppressWarnings("unchecked") private static  Class getGenericType(Class clz) { return (Class) ((ParameterizedType) clz.getGenericSuperclass()) .getActualTypeArguments()[0]; } private static  T getInitialValue(Class clz) { if (clz == Byte.class) { return clz.cast((byte) 0); } else if (clz == Short.class) { return clz.cast((short) 0); } else if (clz == Integer.class) { return clz.cast((int) 0); } else if (clz == Double.class) { return clz.cast((double) 0); } else if (clz == Float.class) { return clz.cast((float) 0); } else if (clz == Long.class) { return clz.cast((long) 0); } else { throw new IllegalArgumentException("Unsupported type: " + clz.getName()); } } } 

PrimitiveNumberRef实例化如下:

 Ref val1 = new PrimitiveNumberRef() { };