1

我想用泛型在运行时解析类型。这是我的代码。

public class NewClas {
    public static void main(String[] args) {
        Object object = null;
        String string = null;
        Integer integer = null;
        // with out generics
        print(object);
        print(string);
        print(integer);
        // print(null); // this won't complile

        // with generics
        Verify<Object> objectVerify = new Verify<Object>();
        Verify<String> stringVerify = new Verify<String>();
        Verify<Integer> integerVerify = new Verify<Integer>();

        objectVerify.call();
        stringVerify.call();
        integerVerify.call();

    }

    public static void print(Object obj) {
        System.out.println("Obj");
    }

    public static void print(String string) {
        System.out.println("string");
    }

    public static void print(Integer integer) {
        System.out.println("Int");
    }
}

// if T extends String then only print(String string) will call
class Verify<T> {
public T obj = null;

    public void call() {
        print(obj);
    }

    // even this is not working
    /*public <T> void call() {
        print((T)obj);
    }*/

    public  void print(Object obj) {
        System.out.println("Obj");
    }

    public  void print(String string) {
        System.out.println("string");
    }

    public  void print(Integer integer) {
        System.out.println("Int");
    }
}

如何在泛型类中使用/调用方法 print(String string),print(Integer integer)。

即使我尝试过

stringVerify.obj =  new String();
stringVerify.call();

这是使用对象签名调用相同的方法。

还尝试了以下操作,它也使用对象签名调用相同的方法。

Verify<String> stringVerify = new Verify<String>() {};
stringVerify.obj =  new String();
stringVerify.call();

对于所有上述情况,输出将是。

Obj
string
Int
Obj
Obj
Obj

以下是我想要的

Obj
string
Int
Obj
string
Int

请教育我。

4

4 回答 4

0

您的代码可以正常工作。前三个结果是正确的,因为方法重载是在编译时解决的。这意味着将使用签名参数与调用方法时使用的参数类型匹配的方法。

关于从验证类进行的调用,您必须考虑到类型信息在编译时会被删除。这意味着对于您的类的所有实例,obj 变量的类型将是 Object。因此,将为所有调用打印相同的结果(对象)。

如果您将<T extends String>其用作 Verify 类的类型声明,则在编译时 obj 引用变量将是 String 类型。

你可以像这样修改你的类,但这不允许你传递一个空对象,因为它会抛出一个 NPE:

 public Verify(T obj) {
    this.obj = obj;
    this.type = (Class<T>) this.obj.getClass();
 }

 public void call() {
    if (type == Object.class) {
        print(obj);
    } else if (type == String.class) {
        print((String) obj);
    } else if (type == Integer.class) {
        print((Integer) obj);
    }
}

您还可以将类作为显式参数发送,并且不会抛出 NPE:

    private Class<T> type = null;

    public Verify(Class<T> type, T obj) {
       this.obj = obj;
       this.type = type;
    }
于 2018-03-30T09:24:50.690 回答
0

试试这个实现:

class Verify<T> {
        public final T obj;

        Verify(T obj) {
            this.obj = obj;
        }


        public void print() {

            switch (obj.getClass().getSimpleName()) {
                case  "String" :
                    System.out.print("string");
                    break;
                case "Integer" :
                    System.out.print("Int");
                    break;
                 default:
                     System.out.print("Object");
            }
        }

    }
于 2018-03-30T09:24:56.600 回答
0

在验证类的调用方法中检查 instanceof:

public void call() {
 if(obj.instanceof(String)) {
    print((String)obj);
 } else if (obj.instanceof(Integer) {
    print((Integer)obj)
 }
于 2018-03-30T09:21:04.690 回答
0

泛型类型擦除。在您的情况下,泛型类型<T>已擦除为Object.

有关更多信息,请阅读此文档

https://docs.oracle.com/javase/tutorial/java/generics/erasure.html

对不起,我的英语不好。

于 2018-03-30T09:54:48.537 回答