我正在阅读有关通用类型的Oracle教程,第一段确实让我很头疼。该页面位于https://docs.oracle.com/javase/tutorial/java/generics/types.html,该教程以名为“ Box”的类开始:
public class Box {
private Object object;
public void set(Object object) { this.object = object; }
public Object get() { return object; }
}
下面的段落也是我一生都无法理解的一段,它的内容是:
由于它的方法接受或返回一个Object,因此只要它不是原始类型之一,就可以随意传递任何所需的对象。在编译时无法验证类的使用方式。代码的一部分可能会将Integer放在框中,并期望从中取出Integer,而代码的另一部分可能会错误地传入String,从而导致运行时错误。
最后一句话对我来说绝对没有意义,而且我已经阅读了该特定页面的其余部分,但仍然无法确切知道他们想说的是什么,感觉好像我错过了大部分内容课。将某些东西“放置”在盒子里是什么意思?
我已经尝试了一切,我尝试以一千种不同的方式实例化Box类,这才有意义,它们都导致编译时错误而不是运行时错误。无论我从哪个角度看,我都无法理解这一点,难以理解这意味着什么
答案 0 :(得分:5)
由于我们处于Box
类的上下文中-一个类是物理盒子的抽象-将整数“放置”到盒子中只是说“设置{{1 }}字段插入object
”的实例。
至于您的评论:
好像他们首先说我可以通过任何东西,然后他们说我不能通过
这就是最后一句话的意思:您可能会有这样的代码:
Integer
本教程所指的“代码的另一部分”是“ ...”部分。如果“ ...”实际上有这样的一行:
Box b = new Box();
b.set(1); // I've put an integer into the box, I should be able to get integers out of it later on
...
Integer i = (Integer)b.get();
然后最后一行将引发异常。
泛型通过使类似b.set("String"); // I forgot that I'm supposed to only put Integers in the box
的编译器错误来解决此问题。
答案 1 :(得分:0)
Box
的每个实例都有一个字段Object object
。将Box
中的内容“放置”表示“将该字段设置为值”(通过使用某个参数调用set(...)
方法)。
例如,让我们假设我们有一个Box box = new Box();
。如果我们调用box.set("Hello")
,则box
的{{1}}将被设置为object
。结果,我们可以String "Hello"
,并且String s = (String) box.get();
将引用s
。由于String "Hello"
返回get()
,我们必须强制转换结果。
现在想象有人打电话给Object
。 box.set(new Integer(10));
不是Integer
,并且String
也不是String
的超类。因此,当我们现在调用Integer
时,对String s = (String) box.get()
的强制转换将在运行时失败,并带有String
。
如果我们有可能以某种方式声明我们要使用的框将容纳ClassCastException
或Integer
,则可以在编译时检测到该错误,或者无论我们要存储在其中。那就是泛型出现的地方。我们可以这样写
String
有了这个功能,我们可以创建包含public class Box<T> {
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
(Box
)的String
和包含Box<String> stringBox = new Box<String>();
({{1} }。以下是一些情况及其各自行为的列表:
Box
我们将问题检测从运行时移到了编译时,并完善了fail-fast设计。很好,不是吗?
答案 2 :(得分:0)
以下是该段落所讨论的情况:
该代码可以编译并成功运行。
Box b = new Box();
b.set(42.0);
double root = Math.sqrt((Double)b.get());
System.out.println(root);
该代码可以编译,但是有运行时错误。
Box b = new Box();
b.set("hello");
double root = Math.sqrt((Double)b.get());
System.out.println(root);
标题为“ Place”的问题的真实答案仅用于本教程试图使用的方框隐喻。他们只是在谈论调用set
方法。
答案 3 :(得分:-1)
老实说,我认为这只是指课程,而不是虚构的“盒子”。泛型允许您限制在该类的特定实例中可以使用哪些数据。使用Objects
代替Generics
不会有相同的限制-由于Java中的所有类都是Object
的子类,因此您可以将任何数据类型传递给它,这可能会导致Java将尝试对这些对象执行某些操作/调用方法时发生运行时错误。