问题:

Java中的原始类型是什么?为什么我经常听到不应该在新代码中使用它们?如果我们不能使用原始类型,还有什么替代方法?如何更好?


当前回答

避免使用原始类型。

原始类型是指在不指定类型参数的情况下使用泛型类型。

例如:

列表是原始类型,而list<String>是参数化类型。

当JDK1.5中引入泛型时,原始类型仅被保留以保持与旧版本Java的向后兼容性。

尽管仍然可以使用原始类型,但应避免使用:

他们通常需要石膏。它们不是类型安全的,一些重要类型的错误只会在运行时出现。它们的表达力较低,并且不像参数化类型那样自我文档化。。

例子:

import java.util.*;
public final class AvoidRawTypes {
    void withRawType() {
        //Raw List doesn't self-document, 
        //doesn't state explicitly what it can contain
        List stars = Arrays.asList("Arcturus", "Vega", "Altair");
        Iterator iter = stars.iterator();
        while (iter.hasNext()) {
            String star = (String) iter.next(); //cast needed
            log(star);
        }
    }

    void withParameterizedType() {
        List < String > stars = Arrays.asList("Spica", "Regulus", "Antares");
        for (String star: stars) {
            log(star);
        }
    }

    private void log(Object message) {
        System.out.println(Objects.toString(message));
    }
}
 

供参考:https://docs.oracle.com/javase/tutorial/java/generics/rawTypes.html

其他回答

当原始类型表达您想要表达的内容时,它们是很好的。

例如,取消序列化函数可能返回List,但它不知道列表的元素类型。所以List是这里合适的返回类型。

教程页面。

原始类型是没有任何类型参数的泛型类或接口的名称。例如,给定泛型Box类:

public class Box<T> {
    public void set(T t) { /* ... */ }
    // ...
}

要创建Box的参数化类型,请为正式类型参数T提供一个实际的类型参数:

Box<Integer> intBox = new Box<>();

如果省略了实际类型参数,则创建原始类型Box:

Box rawBox = new Box();

意思是你的列表是一个未指定对象的列表。也就是说,Java不知道列表中有什么类型的对象。然后,当您想要迭代列表时,必须强制转换每个元素,以便能够访问该元素的财产(在本例中为String)。

一般来说,将集合参数化是一个更好的主意,因此您不会遇到转换问题,您只能添加参数化类型的元素,编辑器将为您提供合适的选择方法。

private static List<String> list = new ArrayList<String>();

原始类型是在使用泛型类型时缺少类型参数。

不应使用原始类型,因为它可能会导致运行时错误,例如将双精度值插入到一组int中。

Set set = new HashSet();
set.add(3.45); //ok

当从集合中检索内容时,你不知道会发生什么。让我们假设您希望它是所有整数,您将其转换为整数;当出现双3.45时,运行时出现异常。

将类型参数添加到Set后,您将立即收到编译错误。这种抢先错误允许您在运行时发生问题之前修复问题(从而节省时间和精力)。

Set<Integer> set = new HashSet<Integer>();
set.add(3.45); //NOT ok.

在这里,我考虑了多个案例,通过这些案例,你可以明确概念

1. ArrayList<String> arr = new ArrayList<String>();
2. ArrayList<String> arr = new ArrayList();
3. ArrayList arr = new ArrayList<String>();

案例1

ArrayList<String>arr它是一个类型为String的ArrayList引用变量,它引用的是一个字符串类型的ArralyList对象。这意味着它只能保存String类型的Object。

它是一个Strict to String,而不是Raw类型,因此它不会引发警告。

    arr.add("hello");// alone statement will compile successfully and no warning.

    arr.add(23);  //prone to compile time error.
     //error: no suitable method found for add(int)

案例2

在这种情况下,ArrayList<String>arr是一个严格类型,但您的Object new ArrayList();是原始类型。

    arr.add("hello"); //alone this compile but raise the warning.
    arr.add(23);  //again prone to compile time error.
    //error: no suitable method found for add(int)

这里arr是严格类型。所以,当添加整数时,它会引发编译时错误。

警告:-原始类型对象引用到ArrayList的严格类型引用变量。

案例3

在本例中,ArrayList arr是一个原始类型,但Object new ArrayList<String>();是严格类型。

    arr.add("hello");  
    arr.add(23);  //compiles fine but raise the warning.

它将向其中添加任何类型的对象,因为arr是一种原始类型。

警告:-严格类型对象引用到原始类型引用的变量。