问题:
Java中的原始类型是什么?为什么我经常听到不应该在新代码中使用它们?如果我们不能使用原始类型,还有什么替代方法?如何更好?
问题:
Java中的原始类型是什么?为什么我经常听到不应该在新代码中使用它们?如果我们不能使用原始类型,还有什么替代方法?如何更好?
当前回答
Java中的原始类型是什么?为什么我经常听到不应该在新代码中使用它们?
原始类型是Java语言的古老历史。最初有集合,它们只持有对象。对集合的每个操作都需要将对象强制转换为所需类型。
List aList = new ArrayList();
String s = "Hello World!";
aList.add(s);
String c = (String)aList.get(0);
虽然这在大多数时间都有效,但确实发生了错误
List aNumberList = new ArrayList();
String one = "1";//Number one
aNumberList.add(one);
Integer iOne = (Integer)aNumberList.get(0);//Insert ClassCastException here
旧的无类型集合无法强制执行类型安全,因此程序员必须记住他在集合中存储的内容。泛型是为了克服这个限制而发明的,开发人员只需声明一次存储的类型,编译器就会改为声明。
List<String> aNumberList = new ArrayList<String>();
aNumberList.add("one");
Integer iOne = aNumberList.get(0);//Compile time error
String sOne = aNumberList.get(0);//works fine
用于比较:
// Old style collections now known as raw types
List aList = new ArrayList(); //Could contain anything
// New style collections with Generics
List<String> aList = new ArrayList<String>(); //Contains only Strings
Comparable接口更复杂:
//raw, not type save can compare with Other classes
class MyCompareAble implements CompareAble
{
int id;
public int compareTo(Object other)
{return this.id - ((MyCompareAble)other).id;}
}
//Generic
class MyCompareAble implements CompareAble<MyCompareAble>
{
int id;
public int compareTo(MyCompareAble other)
{return this.id - other.id;}
}
请注意,无法使用原始类型的compareTo(MyCompareAble)实现CompareAbble接口。为什么不应该使用它们:
存储在集合中的任何对象都必须在使用之前进行强制转换使用泛型启用编译时检查使用原始类型与将每个值存储为Object相同
编译器的作用:泛型是向后兼容的,它们使用与原始类型相同的java类。神奇之处主要发生在编译时。
List<String> someStrings = new ArrayList<String>();
someStrings.add("one");
String one = someStrings.get(0);
将编译为:
List someStrings = new ArrayList();
someStrings.add("one");
String one = (String)someStrings.get(0);
这与直接使用原始类型时编写的代码相同。虽然我不确定CompareAble接口会发生什么,但我猜它会创建两个compareTo函数,一个接受MyCompareAbl,另一个接受Object并在强制转换后将其传递给第一个。
原始类型的替代方法是什么:使用泛型
其他回答
private static List<String> list = new ArrayList<String>();
您应该指定类型参数。
警告建议,应将定义为支持泛型的类型参数化,而不是使用其原始形式。
List被定义为支持泛型:公共类List<E>。这允许在编译时检查许多类型安全操作。
在这里,我考虑了多个案例,通过这些案例,你可以明确概念
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是一种原始类型。
警告:-严格类型对象引用到原始类型引用的变量。
当原始类型表达您想要表达的内容时,它们是很好的。
例如,取消序列化函数可能返回List,但它不知道列表的元素类型。所以List是这里合适的返回类型。
意思是你的列表是一个未指定对象的列表。也就是说,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.