java:jdk1.4和jdk1.5的有那些区别(越详细越好)?

没多大区别,只要你注意别用那些过时的方法就行,若是新版本加的或有改变的方法,docs里会说的,在方法解释下面 jdk6.0将会有很大变化 增强的for循环 为了迭代集合和数组,增强的for循环提供了 ......

没多大区别,只要你注意别用那些过时的方法就行,若是新版本加的或有改变的方法,docs里会说的,在方法解释下面 jdk6.0将会有很大变化 增强的for循环 为了迭代集合和数组,增强的for循环提供了一个简单、兼容的语法。有两点值得一提: Init表达式 在循环中,初始化表达式只计算一次。这意味着您通常可以移除一个变量声明。在这个例子中,我们必须创建一个整型数组来保存computeNumbers()的结果,以防止每一次循环都重新计算该方法。您可以看到,下面的代码要比上面的代码整洁一些,并且没有泄露变量numbers: 未增强的For: int sum = 0; Integer[] numbers = computeNumbers(); for (int i=0; i 1) { Exception e = (Exception)objects[1]; // Do something with the exception } } 方法签名应该如下所示,相应的可变参数分别使用String和Exception声明: Log.log(String message, Exception e, Object... objects) {...} 不要使用可变参数破坏类型系统。需要强类型化时才可以使用它。对于这个规则,PrintStream.printf()是一个有趣的例外:它提供类型信息作为自己的第一个参数,以便稍后可以接受那些类型。 协变返回 协变返回的基本用法是用于在已知一个实现的返回类型比API更具体的时候避免进行类型强制转换。在下面这个例子中,有一个返回Animal对象的Zoo接口。我们的实现返回一个AnimalImpl对象,但是在JDK 1.5之前,要返回一个Animal对象就必须声明。: public interface Zoo { public Animal getAnimal(); } public class ZooImpl implements Zoo { public Animal getAnimal(){ return new AnimalImpl(); } } 协变返回的使用替换了三个反模式: 直接字段访问。为了规避API限制,一些实现把子类直接暴露为字段: ZooImpl._animal 另一种形式是,在知道实现的实际上是特定的子类的情况下,在调用程序中执行向下转换: ((AnimalImpl)ZooImpl.getAnimal()).implMethod(); 我看到的最后一种形式是一个具体的方法,该方法用来避免由一个完全不同的签名所引发的问题: ZooImpl._getAnimal(); 这三种模式都有它们的问题和局限性。要么是不够整洁,要么就是暴露了不必要的实现细节。 协变 协变返回模式就比较整洁、安全并且易于维护,它也不需要类型强制转换或特定的方法或字段: public AnimalImpl getAnimal(){ return new AnimalImpl(); } 使用结果: ZooImpl.getAnimal().implMethod(); 使用泛型 我们将从两个角度来了解泛型:使用泛型和构造泛型。我们不讨论List、Set和Map的显而易见的用法。知道泛型集合是强大的并且应该经常使用就足够了。 我们将讨论泛型方法的使用以及编译器推断类型的方法。通常这些都不会出问题,但是当出问题时,错误信息会非常令人费解,所以需要了解如何修复这些问题。 泛型方法 除了泛型类型,Java 5还引入了泛型方法。在这个来自java.util.Collections的例子中,构造了一个单元素列表。新的List的元素类型是根据传入方法的对象的类型来推断的: static List Collections.singletonList(T o) 示例用法: public List getListOfOne() { return Collections.singletonList(1); } 在示例用法中,我们传入了一个int。所以方法的返回类型就是List。编译器把T推断为Integer。这和泛型类型是不同的,因为您通常不需要显式地指定类型参数。 这也显示了自动装箱和泛型的相互作用。类型参数必须是引用类型:这就是为什么我们得到的是List而不是List。 不带参数的泛型方法 emptyList()方法与泛型一起引入,作为java.util.Collections中EMPTY_LIST字段的类型安全置换: static List Collections.emptyList() 示例用法: public List getNoIntegers() { return Collections.emptyList(); } 与先前的例子不同,这个方法没有参数,那么编译器如何推断T的类型呢?基本上,它将尝试使用一次参数。如果没有起作用,它再次尝试使用返回或赋值类型。在本例中,返回的是List,所以T被推断为Integer。 如果在返回语句或赋值语句之外的位置调用泛型方法会怎么样呢?那么编译器将无法执行类型推断的第二次传送。在下面这个例子中,emptyList()是从条件运算符内部调用的: public List getNoIntegers() { return x ? Collections.emptyList() : null; } 因为编译器看不到返回上下文,也不能推断T,所以它放弃并采用Object。您将看到一个错误消息,比如:“无法将List转换为List。” 为了修复这个错误,应显式地向方法调用传递类型参数。这样,编译器就不会试图推断类型参数,就可以获得正确的结果: return x ? Collections.emptyList() : null; 这种情况经常发生的另一个地方是在方法调用中。如果一个方法带一个List参数,并且需要为那个参数调用这个传递的emptyList(),那么也需要使用这个语法。 集合之外 这里有三个泛型类型的例子,它们不是集合,而是以一种新颖的方式使用泛型。这三个例子都来自标准的Java库: Class Class在类的类型上被参数化了。这就使无需类型强制转换而构造一个newInstance成为可能。 Comparable Comparable被实际的比较类型参数化。这就在compareTo()调用时提供了更强的类型化。例如,String实现Comparable。对除String之外的任何东西调用compareTo(),都会在编译时失败。 Enum> Enum被枚举类型参数化。一个名为Color的枚举类型将扩展Enum。getDeclaringClass()方法返回枚举类型的类对象,在这个例子中就是一个Color对象。它与getClass()不同,后者可能返回一个无名类。 通配符 泛型最复杂的部分是对通配符的理解。我们将讨论三种类型的通配符以及它们的用途。 首先让我们了解一下数组是如何工作的。可以从一个Integer[]为一个Number[]赋值。如果尝试把一个Float写到Number[]中,那么可以编译,但在运行时会失败,出现一个ArrayStoreException: Integer[] ia = new Integer[5]; Number[] na = ia; na[0] = 0.5; // compiles, but fails at runtime 如果试图把该例直接转换成泛型,那么会在编译时失败,因为赋值是不被允许的: List iList = new ArrayList(); List nList = iList; // not allowed nList.add(0.5); 如果使用泛型,只要代码在编译时没有出现警告,就不会遇到运行时ClassCastException。 上限通配符 我们想要的是一个确切元素类型未知的列表,这一点与数组是不同的。 List是一个列表,其元素类型是具体类型Number。 List是一个确切元素类型未知的列表。它是Number或其子类型。 上限 如果我们更新初始的例子,并赋值给List,那么现在赋值就会成功了: List iList = new ArrayList(); List nList = iList; Number n = nList.get(0); nList.add(0.5); // Not allowed 我们可以从列表中得到Number,因为无论列表的确切元素类型是什么(Float、Integer或Number),我们都可以把它赋值给Number。 我们仍然不能把浮点类型插入列表中。这会在编译时失败,因为我们不能证明这是安全的。如果我们想要向列表中添加浮点类型,它将破坏iList的初始类型安全——它只存储Integer。 通配符给了我们比数组更多的表达能力。 为什么使用通配符 在下面这个例子中,通配符用于向API的用户隐藏类型信息。在内部,Set被存储为CustomerImpl。而API的用户只知道他们正在获取一个Set,从中可以读取Customer。 此处通配符是必需的,因为无法从Set向Set赋值: public class CustomerFactory { private Set _customers; public Set getCustomers() { return _customers; } } 通配符和协变返回 通配符的另一种常见用法是和协变返回一起使用。与赋值相同的规则可以应用到协变返回上。如果希望在重写的方法中返回一个更具体的泛型类型,声明的方法必须使用通配符: public interface NumberGenerator { public List generate(); } public class FibonacciGenerator extends NumberGenerator { public List generate() { ... } } 如果要使用数组,接口可以返回Number[],而实现可以返回Integer[]。 下限 我们所谈的主要是关于上限通配符的。还有一个下限通配符。List是一个确切“元素类型”未知的列表,但是可能是Mnumber,或者Number的超类型。所以它可能是一个List或一个List。 下限通配符远没有上限通配符那样常见,但是当需要它们的时候,它们就是必需的。 下限与上限 List readList = new ArrayList(); Number n = readList.get(0); List writeList = new ArrayList(); writeList.add(new Integer(5)); 第一个是可以从中读数的列表。 第二个是可以向其写数的列表。 无界通配符 最后,List列表的内容可以是任何类型,而且它与List几乎相同。可以随时读取Object,但是不能向列表中写入内容。 公共API中的通配符 总之,正如前面所说,通配符在向调用程序隐藏实现细节方面是非常重要的,但即使下限通配符看起来是提供只读访问,由于remove(int position)之类的非泛型方法,它们也并非如此。如果您想要一个真正不变的集合,可以使用java.util.Collection上的方法,比如unmodifiableList()。 编写API的时候要记得通配符。通常,在传递泛型类型时,应该尝试使用通配符。它使更多的调用程序可以访问API。 通过接收List而不是List,下面的方法可以由许多不同类型的列表调用: void removeNegatives(List list); 构造泛型类型 现在我们将讨论构造自己的泛型类型。我们将展示一些例子,其中通过使用泛型可以提高类型安全性,我们还将讨论一些实现泛型类型时的常见问题。 集合风格(Collection-like)的函数 第一个泛型类的例子是一个集合风格的例子。Pair有两个类型参数,而且字段是类型的实例: public final class Pair,b>