繁体   English   中英

转换和泛型如何工作?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM