问题:
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并在强制转换后将其传递给第一个。
原始类型的替代方法是什么:使用泛型
其他回答
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并在强制转换后将其传递给第一个。
原始类型的替代方法是什么:使用泛型
当原始类型表达您想要表达的内容时,它们是很好的。
例如,取消序列化函数可能返回List,但它不知道列表的元素类型。所以List是这里合适的返回类型。
避免使用原始类型。
原始类型是指在不指定类型参数的情况下使用泛型类型。
例如:
列表是原始类型,而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<E>的原始类型),不应该使用原始类型。它们的存在是为了与旧版本的Java兼容。我们希望尽快(编译时)发现错误,使用原始类型可能会在运行时导致错误。在两种情况下,我们仍然需要使用原始类型:
类文字的用法(List.class)instanceof的用法
示例:
//Use of raw type : don't !
private final Collection stamps = ...
stamps.add(new Coin(...)); //Erroneous insertion. Does not throw any error
Stamp s = (Stamp) stamps.get(i); // Throws ClassCastException when getting the Coin
//Common usage of instance of
if (o instanceof Set){
Set<?> = (Set<?>) o;
}
我在做了一些示例练习后发现了这一页,并有着完全相同的困惑。
===============我根据示例提供的代码===============
public static void main(String[] args) throws IOException {
Map wordMap = new HashMap();
if (args.length > 0) {
for (int i = 0; i < args.length; i++) {
countWord(wordMap, args[i]);
}
} else {
getWordFrequency(System.in, wordMap);
}
for (Iterator i = wordMap.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
System.out.println(entry.getKey() + " :\t" + entry.getValue());
}
=========================到此代码========================
public static void main(String[] args) throws IOException {
// replace with TreeMap to get them sorted by name
Map<String, Integer> wordMap = new HashMap<String, Integer>();
if (args.length > 0) {
for (int i = 0; i < args.length; i++) {
countWord(wordMap, args[i]);
}
} else {
getWordFrequency(System.in, wordMap);
}
for (Iterator<Entry<String, Integer>> i = wordMap.entrySet().iterator(); i.hasNext();) {
Entry<String, Integer> entry = i.next();
System.out.println(entry.getKey() + " :\t" + entry.getValue());
}
}
===============================================================================
这可能更安全,但花了4个小时来驳斥哲学。。。