List listOfEmployeeName = new ArrayList(); 在JDK1.5中,你将使用下面语句 List<String> listOfEmployeeName = new ArrayList<String>(); 最“酷”的是,若你试图插入非string类型的值,你将在编译时发现并且修正这类问题。没有泛型,你会发现这样一个bug,当你的客户调用后会告 诉你,你所编写的程序抛出ClassCastException异常而崩溃。 另外,当你从集合中得到一个元素时你无需进行强制转换。故原先为: String employeeName = ((String) listOfEmployee.get(i)); 而下面的语句将比上面的更加简单: String employeeName = listOfEmployee.get(i); 不清楚对象的类型而强制转换对象是不合理的,且更重要的是,它将在运行时失败。假使用户无意间传入一个包含string buffers类型而非string类型的集合,那结果会怎样呢。在Listing A中,客户被要求传入一个编译器无法强制的strings类型集合。Listing B中显示了同样的方法使用泛型是如何实现的。 Listing A static boolean checkName(Collection employeeNameList, String name) { for (Iteratori = employeeNamList.iterator(); i.hasNext(); ) { String s = (String) i.next(); if(s.equals(name)){ return true; //print employee name here ...... } } return false; } Listing B static boolean checkName(Collection employeeNameList, String name) { for (Iteratori = employeeNamList.iterator(); i.hasNext(); ) { if(i.next().equals(name)){ return true; //print employee name here ...... } } return false; } 现在,通过方法签名可以清楚知道输入集合必须只能包含strings。如果客户试图传入一个包含string buffers的集合,程序将不会编译。同时注意,该方法不包含任何强制转换。它只需要短短一行,一旦你习惯泛型后,它也更加清晰。
2、在JDK当前版本下的For循环语法如下:
void printAll(Collection c) { for (Iteratori = c.iterator(); i.hasNext(); ) { Employee emp = (Employee)i.next(); System.out.println(emp.getName()); } } 现在,用增强的For语句实现相同方法:
void printAll(Collection c) { for (Object o : c) System.out.println((TimerTask)o).getName()); } 在这类For循环中,你应该将":"看成"in",所以,在该例中可以看成"for Object o in c"。你可以发现这种For循环更具可读性。
3、自动置入/自动取出(Autoboxing/unboxing) Java有基本数据类型,在这些基本数据类型周围又有包装类。通常,编程人员需要将一种类型转换成另一种。看看Listing C.中的代码片断。 Listing C public class Employee { private static final Integer CHILD = new Integer(0); public static void main(String args[]) { //code for adding n to an Integer int n=10; Integer age= new Integer(30); Integer ageAfterTenYear= new Integer(age.intValue +10); } } 请注意,用于计算ageAfterTenYear的内循环代码看上去是多么杂乱。现在,在Listing D.中看看相同的程序使用autoboxing重写后的样子。
Listing D
public class Employee { public static void main(String args[]) { int n=10; Integer age= new Integer(30); Integer ageAfterTenYear= age +10; } } 值得注意的是:先前,若你取出(unbox)Null值,它将变为0。在次代码中,编译器将自动转换Integer为int然后加上10后将其转换回Integer
4、类型安全的枚举(Typesafeenums) 类型安全枚举提供下列特性: 他们提供编译时类型安全。 他们都是对象,因此你不需要将他们放入集合中。 他们作为一种类的实现,因此你可以添加一些方法。 他们为枚举类型提供了合适的命名空间。 他们打印的值具有情报性(informative)― 如果你打印一个整数枚举(intenum),你只是看见一个数字,它可能并不具有情报性。 例一: enum Season { winter, spring, summer, fall } 例二: public enum Coin { penny(1), nickel(5), dime(10), quarter(25);
Coin(int value) { this.value = value; }
private final int value; public int value() { return value; } } 5、静态导入(Static import) 静态导入使代码更易读。通常,你要使用定义在另一个类中的常量(constants),像这样: import org.yyy.pkg.Increment; class Employee { public Double calculateSalary(Double salary{ return salary + Increment.INCREMENT * salary; } } 当时使用静态导入,我们无需为常量名前缀类名就能使用这些常量,像这样: import static org.yyy.pkg.Increment; class Employee { public Double calculateSalary(Double salary{ return salary + INCREMENT * salary; } } 注意,我们可以调用INCREMENT这一常量而不要使用类名Increment.。 6、元数据(Metadata) 元数据特征志于使开发者们借助厂商提供的工具可以进行更简易的开发。看一看Listing E.中的代码。 Listing E import org.yyy.hr; public interface EmployeeI extends Java.rmi.Remote { public String getName() throwsJava.rmi.RemoteException; public String getLocation () throwsJava.rmi.RemoteException; }
public class EmployeeImpl implements EmployeeI { public String getName(){ } public String getLocation (){ } } 通过元数据的支持,你可以改写Listing E中的代码为: import org.yyy.hr; public class Employee { @Remote public String getName() { ... } @Remote public public String getLocation() { ... } } 7线程池 Java5中,对Java线程的类库做了大量扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关内容,为多线程的编程带来了极大便利。为了编写高效稳定可靠的多线程程序,线程部分的新增内容显得尤为重要。
public String demo() { List strList = new ArrayList(); strList.add(“Hello!”); return strList.get(0); } 编译器在检验通过后,将其转换为: public String demo() { List strList = new ArrayList(); //去除类型值 strList.add(“Hello!”); return (String)strList.get(0); //添加转型动作代码(String) }
class GenericClass { T t1; public void method1(T t){ t1 = new T(); //编译错误,T不能与new联用 if (t1 instanceof T) {}; //编译错误,T不能与instanceof联用 }; static T t2; //编译错误,静态字段不能使用T public static void method2(T t){};//编译错误,静态方法不能使用T }
Generic类可以有多个类型参数,且类型参数命名一般为大写单字符。例如Collection类库中的Map声明为: public interface Map { ……; }
public static void printCollection(Collection> c) { //如此遍历Collection的简洁方式也是JDK1.5新引入的 for (Object o : c) { System.out.println(o); } } 这样,既可以将Collection的实例,也可以将Collection的实例作为参数调用printCollection()方法。 然而,要注意一点,你不能往Collection>容器实例中加入任何非null元素,例如如下代码的第三行编译不通过: public static void testAdd(Collection> c) { c.add(null); //编译通过 c.add(“test”); //编译错误 } 很好理解:c中要存放的对象的具体类型不确定,编译器无法验证待添加对象类型的正确性,因此不能加入对象实例;而null可以看作是任一个类的实例,因而允许加入。 另外,尽管c中要存放的对象的类型不确定,但我们知道任何类都是Object子类,因此从c中取出的对象都统一作为Object实例。 更进一步,如果BaseClass代表某个可被继承的类的类名,那么Collection extends BaseClass>代表类型参数值为BaseClass或BaseClass某个子类的任一参数化Collection。对于 Collection extends BaseClass>的实例c,因为c中要存放的对象具体类型不确定,不能往其加入非null对象,但从c中取出的对象都统一作为 BaseClass实例。事实上,你可以把Collection>看作Collection extends Object>的简洁形式。 另一种情形:如果SubClass代表任一个类的类名,那么Collection super SubClass>代表类型参数值为SubClass或SubClass某个祖先类的任一参数化Collection。对于 Collection super SubClass>的实例c,你可以将SubClass实例加入其中,但从中取出的对象都是Object实例。 7 Generic方法 我们可以定义Generic类,同样可以定义Generic方法,即将方法的一个或多个参数的类型参数化,如代码: public static void fromArrayToCollection(T[] a, Collection c) { for (T o : a) { c.add(o); //合法。注意与Collection>的区别 } } 我们可以以如下方式调用fromArrayToCollection(): Object[] oa = new Object[100]; Collection fromArrayToCollection(oa, co); //此时,T即为Object String[] sa = new String[100]; Collection cs = new ArrayList();
通过以上代码可以看出,我们在调用fromArrayToCollection()时,无需明确指定T为何种类型(与Generic类的使用方式不同), 而是像调用一般method一样,直接提供参数值,编译器会根据提供的参数值自动为T赋类型值或提示编译错误(参数值不当)。 考虑如下函数sum() public static long sum(Collection extends Number> numbers) { long sum = 0; for (Number n : numbers) { sum += n.longValue(); } return sum; }
下面我们来仔细看一下这7大新功能: 1 对集合类的语言支持 Java将包含对创建集合类的第一类语言支持。这意味着集合类的创建可以像Ruby和Perl那样了。 原本需要这样: List list = new ArrayList(); list.add("item"); String item = list.get(0); Set set = new HashSet(); set.add("item"); Map map = new HashMap(); map.put("key", 1); int value = map.get("key");
现在你可以这样: List list = ["item"];
String item = list[0];
Set set = {"item"}; Map map = {"key" : 1}; int value = map["key"]; 这些集合是不可变的。
ArcgisEngine实现对地图的放大、缩小和平移:
个人觉得是平移,不过网上的都是漫游,通俗的说就是把一个地图对象从一边拉到另一边而已。就看人说话吧.
具体实现:
一、引入命名空间
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Controls;
二、代码实现.
Given a linked list and a value x, partition it such that all nodes less than x come before nodes greater than or equal to x.
You should preserve the original relative order of th