1

我有这门课,只是为了学习:

public class MyClass{ //Looking for a solution without making my class also generic <Type>  

    //Private Arraylist var to hold the value called myvar 

   public MyClass(ArrayList<MyDesiredType> incoming) {
        //CODE   myVar=incoming  
    }

    public MyDesiredType getType() {
        return myVar.get(0);
    }   
}

有没有办法在没有警告和强制转换和失去类型安全性的情况下从构造函数中推断传入对象到方法的返回类型,但最重要的是没有使整个类 GENERIC (对我来说似乎是多余的)?如果不是,为什么我认为这对编译器不可行?

这是我已经做过的重新表述的问题,但这是我的第一个问题,我学会了如何清楚地揭露它,因为没有人理解。我后来试图编辑原始问题,但一切都被埋没了。我更改并简化了示例并尝试使其简单。原始问题:Java Generics Silly Thing (Why can't I infer the type?)

如果有任何问题,请告诉我,我会删除它。

4

5 回答 5

8

不,那里没有。编译器如何知道要返回什么类型?构造函数中 ArrayList 的泛型类型在编译期间将不知道。您要么必须使整个类通用,要么采用另一种方法。

考虑一下:

public class Test {
    public static void main(String[] args) {
        List<String> arrList = new ArrayList<String>();
        arrList.add("FOO");
        Test test = new Test(arrList);
        String testStr = test.returnWhat();
        System.out.println("testStr");
    }

    private final List myList; //warning

    public <T> Test(List<T> ttype) {
        myList = ttype;
    }

    public <T> T returnWhat() {
        return (T) myList.get(0); //warning
    }
}

这可行,但会在标记行上为您提供警告。所以,如果不使整个类通用,真的没有办法实现你所描述的。因为,如果:

public class Test {


 public static void main(String[] args) {
        List<String> arrList = new ArrayList<String>();
        arrList.add("FOO");
        Test test = new Test(); // now what?
        String testStr = test.returnWhat(0); // no warning...
        JPanel p = test.returnWhat(0); // goes through without warning, real nice...
        test.returnWhat(0); // returns Object

        Test test2 = new Test(arrList);
        test2.addElement(new Object()); // boom, inserted object into list of string.
        String nono = test2.returnWhat(1); // the universe goes down. assign an object to string without warning. even
                                           // though one COULD think the class is generic.
    }

    // private List<T> myList = new ArrayList<T>(); compiler error, T is unknown
    private List myList = new ArrayList();

    public Test() {
        myList.add(new Object());
    }

    public <T> Test(List<T> ttype) {
        myList = ttype;
    }

    public <T> T returnWhat(int index) {
        return (T) myList.get(index);
    }

    public <T> void addElement(T el) {
        myList.add(el);
    }
}

当 myList 被设为通用时,第二个不会编译。在使用默认构造函数的情况下,编译器如何确定 <T> 的类型?

此外,这可能会导致依赖于仅插入某些类型这一事实的集合中的对象出现严重问题。

这将产生以下异常:

Exception in thread "main" java.lang.ClassCastException:
java.lang.Object cannot be cast to java.lang.String     at
Test.main(Test.java:27)

我说服你了吗?

真的很好的问题,顺便说一句。我不得不考虑这个问题。

于 2012-04-26T15:52:40.090 回答
2

当您说您希望编译器“在没有警告和强制转换以及失去类型安全性的情况下将传入的对象从构造函数中推断为方法的返回类型”时,您似乎是在说它应该getType()从输入中推断出结果的构造函数。如果两者都发生在同一个函数中,它可以。问题是对象可能不只存在于一个函数中,因此需要额外的类型信息(泛型类型)在函数之间传递这种对象。

例如,如果我想编写一个接受MyClass对象的函数,我需要知道getType()会返回什么,这样我才能使用返回的值。通过添加一个泛型类型,MyClass我们对它所拥有的内容进行了描述。

另一种看待它的方式MyClass是容器。通过添加泛型,我们说它是特定类型事物的容器,因此我们可以更轻松地预测我们会从中得到什么。

于 2012-04-26T15:59:36.500 回答
1

编译器无法在运行时知道您的数组列表是什么类型。我真的没有看到使用以下内容的问题:

 public class MyClass<TYPE> {
     private ArrayList<TYPE> incoming;

     public MyClass(ArrayList<TYPE> incoming) {
         this.incoming = incoming;
     }

     public TYPE getType() {
         return incoming.get(0);
     }
 }

这样你就可以做到:

ArrayList<Integer> numbers = createListOfNumbers();
MyClass<Integer> myClass = new MyClass<>(numbers);
Integer number = myClass.getType();

还是我误解了这个问题,您想在运行时知道该课程?

于 2012-04-26T15:54:43.857 回答
0

不,如果您想要一个可以保存参数化类型列表的类。

是的,如果您想要一个可以包含仅一种类型的列表的类。您可以在字段、构造函数和访问器中显式声明该类型。

于 2012-04-26T15:50:52.060 回答
0

您忘记的是,并非您可能运行的所有代码对编译器都是可见的!可以在运行时添加、删除、替换 Jar,这是编译器从未见过的。您可以针对以下接口进行编译:

public interface MyClassFactory {
  MyClass getInstance();
}

然后在运行时向 JVM 提供一个实现。因此编译器从未看到创建您将使用的 MyClass 的实际代码,因此无法执行这样的编译时推断。您必须使类成为通用类或接受不存在类型安全的事实。

于 2012-04-26T15:51:20.233 回答