首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >Java --模板中的Byte、Integer、Long等的原始对应物

Java --模板中的Byte、Integer、Long等的原始对应物
EN

Stack Overflow用户
提问于 2016-03-11 17:25:48
回答 1查看 470关注 0票数 0

背景

我正在尝试实现一个很小的模板,即泛型类,它将允许我实现如下所示的按引用传递功能。

代码语言:javascript
代码运行次数:0
运行
复制
public static class Ref<T> {
    T value;
    public Ref(T InitValue)  { this.set(InitValue); }
    public void set(T Value) { this.value = Value; }
    public T    get()        { return this.value; }
}

因此,我可以定义一个函数,该函数接受一个“Ref”,其中实际可以更改该值。

代码语言:javascript
代码运行次数:0
运行
复制
public static void function(Ref<Byte> x)
{
    x.set((byte)0x7E);
}

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

代码语言:javascript
代码运行次数:0
运行
复制
Ref<Byte>  to_be_changed = new Ref<Byte>((byte)0);
...
function(to_be_changed); 
...
Byte       result = to_be_changed.get()

问题

在Java中有什么方法可以做得更好吗?构造函数可以根据与作为模板类型传递的包装器类型相关的基元类型直接初始化'0‘吗?也就是说,就像

代码语言:javascript
代码运行次数:0
运行
复制
 ...
 public Ref() { this.value = (T.relatedPrimitiveClass())0; }
 ...

Integer.relatedPrimitiveClass()将交付intByte.relatedPrimitiveClass()将交付byte

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-03-11 23:46:48

首先,也是最重要的一点是,java泛型不是模板。泛型是对类型进行参数化的类/接口。我建议阅读oracle的泛型教程:https://docs.oracle.com/javase/tutorial/java/generics/types.html

可以使用反射来获得Ref类的参数化类型T,并使用它来确定缺省构造器的初始值,但我不建议这样做。

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

代码语言:javascript
代码运行次数:0
运行
复制
public static class ByteRef extends Ref<Byte> {
    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类添加新方法:

代码语言:javascript
代码运行次数:0
运行
复制
public static class Ref<T> {
    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<Byte> createByteRef() {
        return new Ref<Byte>((byte)0);
    }

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

或者您可以创建单独的工厂类: public类Ref { public静态Ref createByteRef() {返回新的引用((字节)0);}

代码语言:javascript
代码运行次数:0
运行
复制
    public static Ref<Byte> createByteRef(byte value) {
        return new Ref<Byte>(value);
    }
}

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

代码语言:javascript
代码运行次数:0
运行
复制
public abstract static class PrimitiveNumberRef<T extends Number> extends
        Ref<T> {
    private Class<T> 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 <T> Class<T> getGenericType(Class<?> clz) {
        return (Class<T>) ((ParameterizedType) clz.getGenericSuperclass())
                .getActualTypeArguments()[0];
    }

    private static <T> T getInitialValue(Class<T> 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实例化如下:

代码语言:javascript
代码运行次数:0
运行
复制
Ref<Long> val1 = new PrimitiveNumberRef<Long>() { };
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35946321

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档