原始类型和泛型 -- Java

32 浏览
0 Comments

原始类型和泛型 -- Java

可能重复:

List是List的子类吗?为什么Java的泛型不是隐式多态的?

Java泛型 - 将子类列表赋给超类列表

使用原始类型,你可以轻松地这样说。

[...] // MyClass是具有Object上界的泛型
MyClass c = new MyClass();
[...]

但是这是不允许的

MyClass c = new MyClass() 

我不明白为什么会这样。我的书告诉我为什么第二种方式不起作用,因为你不能将Integer添加到MyClass中。它没有解释为什么MyClassMyClass(或等效的原始类型形式)的子类,因为double是object的子类。

所以为什么第一种方式是允许的,而第二种方式不是。请理解我是新手。

编辑:如果Number是上界,第一个示例会发生什么?

你可以在这里看到类型擦除的效果

class Untitled {
public static void main(String[] args) {
}
public static void c(T t)
{
    t.SubClassMethod();// 这不起作用,因为类Object没有这样的方法。但是如果我将上界改为SubClass,它将起作用。
            t.toString() // 这将起作用,因为类Object有这样的方法
}
}

我的观点是,如果最终被视为上界,那么泛型的声明是什么并不重要。

0
0 Comments

原因:问题的原因是因为在使用泛型时,如果将一个泛型对象声明为某个类的泛型类型,然后将其赋值为该类的子类的泛型类型,会导致类型不匹配的错误。这是因为Java的泛型在编译时会进行类型擦除,将泛型类型替换为其上界类型,因此在编译时无法检测到类型不匹配的错误。

解决方法:为了解决这个问题,可以使用通配符来限制泛型的类型。可以使用"?"来表示任意类型,或者使用"extends"关键字限制泛型的上界。通过使用通配符,可以在不知道具体类型的情况下,将一个泛型对象赋值给另一个泛型对象。

以下是修改后的代码示例:

public class MyClass{
  T value;
  public void foo(? extends T arg){
    value = arg;
  }
}
class A{ }
class B extends A { }
MyClass container = new MyClass();
container.foo(new A());

这样修改后的代码可以正确地将一个A对象赋值给一个B类型的泛型对象,避免了类型不匹配的错误。

0
0 Comments

Java中出现原始类型(Raw Type)和泛型(Generics)的问题是为了向后兼容。在Java 5中引入泛型时,一些已有的类和接口被改为泛型。为了使没有泛型声明的旧代码能够在Java 5或更高版本的编译器中编译,原始类型的声明是合法的。

原始类型的行为与参数化类型的行为进行比较,实际上是有些基本上的错误。设计的目的并不是将原始类型视为声明参数的“替代方案”。使用原始类型的新代码是错误的代码。编译器允许编译它以使旧代码仍然可以工作。

泛型的整个目的是防止ClassCastException。当某人从列表中取出对象并将其赋值给他们期望的特定类型时,它将被视为实际声明的类型。编译器承诺保证这将成功,因此必须限制进出的内容。

通过一些深入研究后,我将回答我的问题,并且你完美地回答了。是的,这是有道理的,如果返回类型不一致会发生什么。感谢你澄清了这一点。

唯一我不同意的是它被视为声明的类型而不是上界。当方法或类编译时,我知道唯一的类型转换是在函数返回时转换回参数化类型。其他所有内容都会被隐式转换为上界,并在方法中作为上界对待,这是由于类型擦除。如果我对此正确,请告诉我。

是的,我试图在我拼接得有些混乱的冗长句子中表达这个意思。

0
0 Comments

原因:

Java中出现原始类型和泛型的问题,主要是因为在早期版本的Java中没有引入泛型特性。因此,为了保持向后兼容性,Java允许使用原始类型来表示泛型类型的一种方式。原始类型是指在泛型类或泛型方法中没有指定类型参数的类型。

解决方法:

为了避免使用原始类型,我们可以使用泛型来解决这个问题。泛型允许我们在编译时指定类型参数,并在运行时进行类型检查,从而提高代码的类型安全性和可读性。

在上面的示例中,我们可以看到使用原始类型的问题。为了解决这个问题,我们可以使用泛型来指定类型参数。通过这种方式,我们可以在编译时检查类型,并避免在运行时发生类型转换错误。

下面是使用泛型解决原始类型问题的示例代码:

MyClass c = new MyClass();

在这个示例中,我们使用了通配符"?"来表示类型参数,并使用"extends"关键字来限定类型参数的上界为Number类。这意味着我们可以使用Number类或其子类作为类型参数。

通过使用泛型,我们可以在编译时检查类型,并避免在运行时发生类型转换错误。这提高了代码的类型安全性和可读性。

原始类型和泛型是Java中的一个重要概念。原始类型是为了保持向后兼容性而引入的,但它们在类型安全性和可读性方面存在一些问题。为了解决这个问题,Java引入了泛型特性。通过使用泛型,我们可以在编译时检查类型,并避免在运行时发生类型转换错误。这提高了代码的类型安全性和可读性。

0