我为长期答复道歉。
我不认为你可以用Generics完全达到你想要的效果而不会失去类型安全性。
为了使下一行工作,Java需要知道defer()方法返回了一个Truck ,因此它可以在该对象上调用honk() 。
p.deref().honk();
但是如果你使用Java Generics,那么就会在编译时推断出类型擦除。
该解决方案意味着添加像Pointer这样的通用类型,但我们不能,因为您希望能够添加十几种特定的已知类型和Pointer 。
但是......既然你自己写了那样的那一行,特别是调用bark()或者honk() ,
它意味着你已经知道Pointer在你的代码中引用了Dog或Truck对象。
使用该假设,Generics和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 void ref(T myObject) {
this.myObj = myObject;
}
public T deref(Class 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
}
这将打印出来:
树皮......
哇......
哇......
树皮......
Pointer.main中线程“main”java.lang.NullPointerException中的异常(Pointer.java:39)
如果您需要将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 void ref(T myObject) { this.myObj = myObject; } public T deref(Class myClazz) { try { return myClazz.cast(myObj); } catch(ClassCastException e) { return null; } } }