[英]How does casting and Generics work?
阅读了一些示例后,我仍然不太了解泛型。 到目前为止,我发现的最佳解释是Java中的<>(尖括号)是什么意思?
根据我的阅读,如果您使用泛型,则无需将返回值强制转换为类型。
但是泛型实际上是做什么的呢? 据我了解,是确保返回值已经强制转换为括号中定义的类型。
但这意味着,Java要求强制转换每个分配。
String str = (String) otherstring;
是适当的,并且
String str = otherstring;
是不合适的。
因此,根据我的理解,泛型<String>
将确保在分配值之前对值进行强制转换,因此我们不必强制转换?
Java是否需要每个值都进行强制转换,即使它已经是相同类型了?
从某种意义上说,PHP更容易,但这仅仅是因为它与某些问题无关。 使用PHP,您可以稍后处理这些问题。
投放基本上是在两个方向之一(向上或向下)中进行的。 一个高调的陈述是,您只希望仅通过对象所继承的类的接口(或继承其接口)来使用该对象。
例如,如果我有FileInputStream,则可以将其更改为“ just”一个InputStream
FileInputStream fileInput = ...
InputStream input = (InputStream)fileInput;
请注意,这对可实现方法的实施完全没有影响; 但是有时会隐藏以前可用的方法。
fileInput.getFileName(); // let's pretend this works
input.getFileName(); // this shouldn't work, as any InputStream doesn't have a file name.
向下转换是不同的(并且很危险)。 您基本上说,即使您有一个InputStream,也知道应该将其视为FileInputStream
InputStream input2 = ...;
FileInputStream fileInput2 = (FileInputStream)input2;
如果在这种情况下,input2没有适当类型的FileInputStream,则您将在运行时收到类强制转换异常。 如果确实具有适当的类型,则将分配fileInput2。
使用这种打字系统的主要原因是,您可以轻松编写可重用的组件。 “较高”类型(向下填充类型)指定了常规合同,而“较低”类型(向下填充类型)则指定了在由其超级类型指定的常规合同内变化的特定详细信息。
泛型; 但是,蜡球却不同。 基本上,在处理集合以及与集合相关的事物时,规则是相似的(但由于多种原因,它们必须有所不同)。
泛型行为不同的原因之一是向后兼容。 将“额外”类型信息添加到已经存在的类型(如java.util.List)的设计目标意味着对于混合泛型和非泛型使用,该类型在运行时实际上不存在。 在运行时不认为存在的通用类型的属性称为“擦除”。 简而言之,当你写
List<Student> students = new ArrayList<Student>();
您正在有效地进行编译
List students = new ArrayList();
但是您的编译器将做“额外”工作,以确保在您编写的任何源代码中,您只能添加“ Student”对象。 同样,当您遍历列表时,不需要强制转换为“ Student”对象,因为编译器会假设列表中只能有“ Student”对象。
请注意,要使这样的系统正常工作,它仅是编译时。 这意味着它们不适用类型层次结构和运行时强制转换的详细信息。 这反映在泛型添加的新类型约束中。
T extends Student
表示T可以强制转换为学生(强制转换)
T super Student
表示T是Student的超类。后者很棘手,但在某些情况下很有用。
如果CollegeStudent,HighSchoolStudent和GradeSchoolStudent都扩展了Student,则可以将所有三种类型的Student存储在List <?中。 同时扩展Student>。
如果需要确保某个收藏集至少能提供给学生,那么您可以给出一个列表<? 超级学生>。
public void studentProcessor(Collection<? super Student> students);
可以处理List <Student>,List <CollegeStudent>,List <GradeSchoolStudent>等。
转换和使用泛型之间的区别在于它们是编译时机制。 意思是,下面的代码没有得到运行时异常,而是不会编译:
Clazz <T> c = new Clazz <U> ();
如果T无法转换为U。
通用类为您可以想象的任何对象提供功能-该处理的类有时称为您的参数 。 例如, java.util.List
接口及其实现类(例如ArrayList<E>
)为任意类型E提供了列表功能(添加元素,删除元素,元素计数等)。管理自己的Maroun
类型Maroun
)。 泛型类型的实现必须独立于其处理的参数。 在示例中- List
独立于Maroun
因此,泛型的概念与类型转换几乎没有关系,如您所见;)
当您有一个实例可以通过type参数化的类时,请使用泛型。 常见的例子是集合。
在泛型之前, Collection
包含许多被归类为Object
。 尽管有可能对象具有编译器无法识别的更多特定类型,因此需要危险的运行时转换为实际类型。
现在您可以参数化Collection<E>
,其中E
是元素类型。 现在,编译器可以确保Collection<Foo>
仅添加了Foo
实例,并且它可以返回类型化的Foo
实例,而无需强制转换。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.