1、泛型(Generic)
可以在编译的时候检测出类型错误,编译后和没有使用泛型的效果是相同的,但是使用泛型可以让你在编译时就发现错误,例如:
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.Iterator;
- public class GenericTest {
- public static void main(String[] args) {
- Collection c = new ArrayList();
- c.add(new Integer(1));
- c.add("123");
- for(Iterator i=c.iterator();i.hasNext();){
- String s = (String) i.next();
- System.out.println(s);
- }
- }
- }
- 运行结果:
- Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
- at GenericTest.main(GenericTest.java:12)
Collection应该只存放String对象,但是我们“不小心”添加了一个Integer类型的对象,编译正常进行,程序在运行时才发现错误。
下面是使用了泛型后的程序
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.Iterator;
- public class GenericTest {
- public static void main(String[] args) {
- Collection<String> c = new ArrayList<String>();
- c.add(new Integer(1));
- c.add("123");
- for(Iterator<String> i=c.iterator();i.hasNext();){
- String s = i.next();
- System.out.println(s);
- }
- }
- }
- 运行结果
- D:\test>javac GenericTest.java
- GenericTest.java:8: 无法将 java.util.Collection<java.lang.String> 中的 add(java.lang.String) 应用于 (java.lang.Integer)
- c.add(new Integer(1));
- ^
- 1 错误
- D:\test>
使用了泛型之后在编译时就发现了错误,可以增强程序的健壮性,而其i.next();也不用使用强制类型转换了。
2、增强for循环(For-Each)
For-Each的内部是用Iterator实现的,但是使用起来更简单,例如使用For-Each实现1-2如下
- import java.util.ArrayList;
- import java.util.Collection;
- public class GenericTest {
- public static void main(String[] args) {
- Collection<String> c = new ArrayList<String>();
- c.add("aa");
- c.add("bb");
- for(String s:c){
- System.out.println(s);
- }
- }
- }
- 运行结果:
- aa
- bb
比Integer方便多了吧?可以使程序员更加注重逻辑,而不是代码本身。
3、自动装箱拆箱(Autoboxing/unboxing)
- Integer i = new Integer(2);
- //i自动拆箱为int类型
- System.out.println(i==2);
- //3自动装箱为Integer类型
- System.out.println(i.equals(3));
4、静态导入(static import)
- //静态导入Math的random方法
- import static java.lang.Math.random;
- public class StaticImportTest {
- public static void main(String[] args){
- //类中生成随机数数可以直接使用静态引入的random方法了,而不用Math.random()这样调用了
- System.out.println(random());
- }
- }
5、格式化打印(formatted print)
C语言中printf()风格的格式化输出。
这里只举一个thinking in java的一个例子:
- public class SimpleFormat {
- public static void main(String[] args) {
- int x = 5;
- double y = 5.332542;
- //The old way
- System.out.println("Row 1: ["+x+" "+y+"]");
- //The new way
- System.out.format("Row 1: [%d %f]\n", x,y);
- //or
- System.out.printf("Row 1: [%d %f]\n", x, y);
- }
- }
- 运行结果:
- Row 1: [5 5.332542]
- Row 1: [5 5.332542]
- Row 1: [5 5.332542]
可以看到,format和printf是等价的,他们只需要一个简单的格式化字符串,加上一串参数即可,每个参数对应一个格式修饰符
6、枚举(Enum)
当每一类型可取值范围是有限的时候,可以使用枚举,例如每个学生登记只能用ABCD表示,如果直接用E的话,那么编译不会出错,但是却不符合输入要求,而使用枚举增加程序的易读性和健壮性?
- public class GradeTest {
- public static void main(String[] args) {
- Student stu = new Student();
- stu.setName("wasw100");
- stu.setGrade(Grade.A);
- //输出学生信息
- System.out.println(stu);
- }
- }
- /**
- * 枚举:Grader 学生考试等级
- * @author wasw100
- */
- enum Grade{
- A,B,C,D
- }
- class Student {
- private String name;
- private Grade grade;
- //重写toString()方法
- public String toString(){
- return "name:+"+name+"\ngrader:"+grade;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Grade getGrade() {
- return grade;
- }
- public void setGrade(Grade grade) {
- this.grade = grade;
- }
- }
7、可变长参数(varargs)
方法的参数是不固定的我们一般会使用重载或者使用数组参数。重载需要些更多写更多的方法,数组需要在使用时先声明。
可能参数是一个不错的解决方案。
下面是网上一个 唐僧 给 悟空 将佛经的例子
- public class VarargsTest {
- public void speak(String name, Object... arguments) {
- System.out.print(name+": ");
- for (Object object : arguments) {
- System.out.print(object);
- }
- System.out.println();
- }
- public static void main(String[] args) {
- VarargsTest vt = new VarargsTest();
- vt.speak("悟空", "人和妖精都是妈生的,");
- vt.speak("悟空", "不同的人是人他妈生的,", "妖是妖他妈生的,");
- }
- }
- 运行结果:
- 悟空: 人和妖精都是妈生的,
- 悟空: 不同的人是人他妈生的,妖是妖他妈生的,