3 回答
TA贡献1890条经验 获得超9个赞
这称为联合或变体类型(请参阅C++ 中的Boost.Variant)。后者特别方便,因为它是一组异构类型的类型安全容器,并且最接近您对要移植的代码类型的描述。由于 Java 不支持模板——不,泛型不是模板——你不会得到你正在寻找的东西。
Optional类型是两种类型中最简单的情况:类型 T 和 Null 。鉴于您需要存储的不仅仅是 T 或 Null 类型,它对您不起作用。
您可能想查看JavaSealedUnions。此外,Kotlin 提供了密封类的概念,有助于将值限制为受约束集中的一种类型。
TA贡献1871条经验 获得超8个赞
这是我能想到的最好的。我认为你不能轻易地制作一个通用类型,而不是它是所有类的父类(如对象)。考虑到类型系统,转换也很困难,您可以通过不允许重新分配不同类型的指针来模仿它,而每次执行获取时只生成一个新指针。如果你不想知道类型本身,你可以在现代 java 中使用 var 来隐藏类型差异。
public class Types {
public static void main(String[] args) {
var p = new PascalPointer<>(new PascalInt());
PascalInt i = p.get();
var p2 = new PascalPointer<>(i.toPStr()); // mimic generics by type inference.
PascalString s = p2.get();
PascalPointer<PascalType> genericPointer = new PascalPointer<>(s);
genericPointer.set(i);
var i2 = (PascalInt) genericPointer.get();
}
public interface PascalType { }
public static class PascalInt implements PascalType {
// cast
public PascalString toPStr() {
return new PascalString(); // hide a new to do a conversion instead of a cast really.
}
}
public static class PascalString implements PascalType { }
public static class PascalPointer<T extends PascalType> {
T t;
public PascalPointer(T t) { this.t = t; }
public T get() { return t;}
public void set(T t) {this.t = t;}
}
}
当您想要一个字符串的 Int 视图并更新字符串时,这可能会发生故障(正如我在这里复制的那样)。
TA贡献1770条经验 获得超3个赞
对于冗长的回答,我深表歉意。
我不认为你可以在不失去类型安全的情况下使用泛型实现你想要的。
为了使下一行工作,Java 需要知道Truck该方法返回了一个,defer()以便它可以调用honk()该对象。
p.deref().honk();
但是,如果您使用 Java 泛型,那么这会在编译时推断出类型擦除。
该解决方案意味着添加一个通用类型,例如Pointer<Truck>,但我们不能,因为您希望能够添加十几个特定的已知类型和一个Pointer.
但是......由于您自己编写了这样的行,特别是调用bark()orhonk(),
这意味着您已经知道Pointer引用 aDogorTruck对象。
使用该假设、泛型和对 的修改defer(),您可以非常接近解决方案。
假设我们有这些类,它们没有任何链接。
public class Dog {
public void bark() {
System.out.println("Bark ...");
}
}
public class Truck {
public void honk() {
System.out.println("Honk ...");
}
}
然后我们需要一个像这样的Pointer类,其中deref()方法需要一个Class参数来知道要返回哪个类型。
public class Pointer {
private Object myObj;
public <T> void ref(T myObject) {
this.myObj = myObject;
}
public <T> T deref(Class<T> myClazz) {
try {
return myClazz.cast(myObj);
} catch(ClassCastException e) {
return null;
}
}
}
然后您可以执行以下操作
public static void main(String[] args) {
Pointer pointer = new Pointer();
Dog dog = new Dog();
pointer.ref(dog); // Reference to a Dog
pointer.deref(Dog.class).bark();
Truck truck = new Truck();
pointer.ref(truck); // Reference to a Truck
pointer.deref(Truck.class).honk();
Pointer subPointer = new Pointer();
pointer.ref(subPointer); // Reference to another pointer
subPointer.ref(truck); // Other pointer references a Truck
pointer.deref(Pointer.class).deref(Truck.class).honk();
subPointer.ref(dog); // Other pointer references a Dog
pointer.deref(Pointer.class).deref(Dog.class).bark();
pointer.ref(null); // Clears the reference
Truck bulldog = new Truck();
pointer.ref(bulldog);
pointer.deref(Dog.class).bark(); // Is allowed, but will cause a NullPointerException
}
这将打印出:
Bark ...
Honk ...
Honk ...
Bark ...
在 Pointer.main(Pointer.java:39) 的线程“主”java.lang.NullPointerException 中出现异常
如果您需要将Pointer引用限制为仅对您的十几个特定已知类型和Pointer类本身,那么您需要使用超类(例如Pointerable)扩展它们并相应地修改ref()方法。
然后,您可以防止不扩展此超类的类型被您的指针引用。
例子:
public abstract class Pointerable { }
public class Dog extends Pointerable {
public void bark() {
System.out.println("Bark ...");
}
}
public class Pointer extends Pointerable {
private Object myObj;
public <T extends Pointerable> void ref(T myObject) {
this.myObj = myObject;
}
public <T extends Pointerable> T deref(Class<T> myClazz) {
try {
return myClazz.cast(myObj);
} catch(ClassCastException e) {
return null;
}
}
添加回答
举报