黑马程序员_JavaSE学习总结第27天_反射 & 设计模式 & JDK5、7、8新特性

------- android培训、java培训、期待与您交流! ---------- 

27.01  反射_类的加载概述和加载时机

类的加载:当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。

加载:就是指将class文件读入内存,并为之创建一个Class对象。任何类被使用时系统都会建立一个Class对象。

连接

  验证 是否有正确的内部结构,并和其他类协调一致

  准备 负责为类的静态成员分配内存,并设置默认初始化值

  解析 将类的二进制数据中的符号引用替换为直接引用

初始化:

  创建类的实例

  访问类的静态变量,或者为静态变量赋值

  调用类的静态方法

  使用反射方式来强制创建某个类或接口对应的java.lang.Class对象

  初始化某个类的子类

  直接使用java.exe命令来运行某个主类

27.02  反射_类加载器的概述和分类

类加载器:负责将.class文件加载到内在中,并为之生成对应的Class对象。

类加载器的组成:

Bootstrap ClassLoader 根类加载器

也被称为引导类加载器,负责Java核心类的加载

比如System,String等。在JDK中JRE的lib目录下rt.jar文件中

Extension ClassLoader 扩展类加载器

负责JRE的扩展目录中jar包的加载。

在JDK中JRE的lib目录下ext目录

Sysetm ClassLoader 系统类加载器

负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径

27.03  反射_反射概述

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

 

要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象。

27.04  反射_获取class文件对象的三种方式

1:Object类的getClass()方法

2:数据类型的静态属性class

3:Class类中的静态方法:public static Class forName(String className)

开发中使用第三种方式

例:

 1 public class Practice 

 2 {

 3     public static void main(String[] args) throws ClassNotFoundException

 4     {

 5         // 方式1

 6         Student p = new Student();

 7         Class c1 = p.getClass();

 8 

 9         Student p2 = new Student();

10         Class c2 = p2.getClass();

11 

12         System.out.println(p == p2);// false

13         System.out.println(c1 == c2);// true

14 

15         // 方式2

16         Class c3 = Student.class;

17         System.out.println(c1 == c3);// true

18 

19         // 方式3

20         //public static Class<?> forName(String className) throws ClassNotFoundException

21         //返回与带有给定字符串名的类或接口相关联的 Class 对象

22         Class c4 = Class.forName("com.test.Student");//类的全路径

23         System.out.println(c1 == c4);// true

24     }

25 }

 

 

27.05  反射_通过反射获取无参构造方法并使用

获取无参构造方法

public Constructor<?>[] getConstructors()throws SecurityException

返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。

public Constructor<?>[] getDeclaredConstructors()throws SecurityException

返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。

例1:

 1 Class c = Class.forName("com.test.Student");

 2 //获取所有公共构造方法

 3 Constructor[] cons = c.getConstructors();

 4 for(Constructor con : cons)

 5 {

 6     System.out.println(con);

 7 }

 8 System.out.println("--------------");

 9 //获取所有构造方法

10 Constructor[] conss = c.getDeclaredConstructors();

11 for(Constructor con : conss)

12 {

13     System.out.println(con);

14 }

 

例2:

 1 public class Practice 

 2 {

 3     public static void main(String[] args) throws Exception

 4     {

 5         Class c = Class.forName("com.test.Student");

 6         // 获取单个构造方法

 7         // public Constructor<T> getConstructor(Class<?>... parameterTypes)

 8         // 参数表示的是:要获取的构造方法的构造参数个数及数据类型的class字节码文件对象

 9         Constructor con = c.getConstructor();// 返回的是构造方法对象

10 

11         // Person p = new Person();

12         // System.out.println(p);

13         // public T newInstance(Object... initargs)

14         // 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。

15         Object obj = con.newInstance();

16         System.out.println(obj);

17         

18          //Student p = (Student)obj;

19          //p.show();

20     }

21 }

 

 

27.06  反射_通过反射获取带参构造方法并使用

获取带参构造方法

例: 

 1 public class Practice 

 2 {

 3     public static void main(String[] args) throws Exception 

 4     {

 5         // 获取字节码文件对象

 6         Class c = Class.forName("com.test.Student");

 7 

 8         // 获取带参构造方法对象

 9         // public Constructor<T> getConstructor(Class<?>... parameterTypes)

10         Constructor con = c.getConstructor(String.class, int.class,String.class);

11 

12         // 通过带参构造方法对象创建对象

13         // public T newInstance(Object... initargs)

14         Object obj = con.newInstance("小明", 27, "上海");

15         

16         System.out.println(obj);

17     }

18 }

 

27.07  反射_通过反射获取私有构造方法并使用

获取私有构造方法

 1 public class Practice 

 2 {

 3     public static void main(String[] args) throws Exception 

 4     {

 5         // 获取字节码文件对象

 6         Class c = Class.forName("com.test.Student");

 7 

 8         // 获取私有构造方法对象

 9         Constructor con = c.getDeclaredConstructor(String.class);

10 

11         // 用该私有构造方法创建对象

12         // IllegalAccessException:非法的访问异常。

13         // 暴力访问

14         con.setAccessible(true);// 值为true则指示反射的对象在使用时应该取消Java语言访问检查

15         Object obj = con.newInstance("旺财");

16 

17         System.out.println(obj);

18     }

19 }

 

27.08  反射_通过反射获取成员变量并使用

获取成员变量

public Field getField(String name)throws NoSuchFieldException,SecurityException

返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。

public Field[] getDeclaredFields()throws SecurityException

返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。

例:

 1 public class Practice 

 2 {

 3     public static void main(String[] args) throws Exception 

 4     {

 5         // 获取字节码文件对象

 6         Class c = Class.forName("com.test.Student");

 7 

 8         // 通过无参构造方法创建对象

 9         Constructor con = c.getConstructor();

10         Object obj = con.newInstance();

11         System.out.println(obj);

12 

13         // 获取单个的成员变量

14         // 获取address并对其赋值(公共的)

15         Field addressField = c.getField("address");

16         // public void set(Object obj,Object value)

17         // 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。

18         addressField.set(obj, "上海"); // 给obj对象的addressField字段设置值为"上海"

19         System.out.println(obj);

20 

21         // 获取name并对其赋值(私有的)

22         // NoSuchFieldException

23         Field nameField = c.getDeclaredField("name");

24         // IllegalAccessException

25         nameField.setAccessible(true);

26         nameField.set(obj, "小强");

27         System.out.println(obj);

28 

29         // 获取age并对其赋值(默认的)

30         Field ageField = c.getDeclaredField("age");

31         ageField.setAccessible(true);

32         ageField.set(obj, 27);

33         System.out.println(obj);

34     }

35 }

 

27.09  反射_通过反射获取无参无返回值成员方法并使用

获取无参无返回值成员方法

public Method[] getMethods()throws SecurityException

返回本类的所有公共方法同时返回从 Object 类继承的所有公共方法。

public Method[] getDeclaredMethods()throws SecurityException

返回 自己的所有方法

例:

 1 public class Practice 

 2 {

 3     public static void main(String[] args) throws Exception 

 4     {

 5         // 获取字节码文件对象

 6         Class c = Class.forName("com.test.Student");

 7 

 8         Constructor con = c.getConstructor();

 9         Object obj = con.newInstance();

10 

11         // 获取单个方法并使用

12         // public void show()

13         // public Method getMethod(String name,Class<?>... parameterTypes)

14         // 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型

15         Method m1 = c.getMethod("show");

16         // obj.m1(); // 错误

17         // public Object invoke(Object obj,Object... args)

18         // 返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数

19         m1.invoke(obj); // 调用obj对象的m1方法

20     }

21 }

 

27.10  反射_通过反射获取带参带返回值成员方法并使用

获取带参带返回值成员方法

例:

 1 public class Practice 

 2 {

 3     public static void main(String[] args) throws Exception 

 4     {

 5         // 获取字节码文件对象

 6         Class c = Class.forName("com.test.Student");

 7 

 8         Constructor con = c.getConstructor();

 9         Object obj = con.newInstance();

10 

11         // 获取单个方法并使用

12         // public void show()

13         // public Method getMethod(String name,Class<?>... parameterTypes)

14         // 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型

15         Method m1 = c.getMethod("show");

16         // obj.m1(); // 错误

17         // public Object invoke(Object obj,Object... args)

18         // 返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数

19         m1.invoke(obj); // 调用obj对象的m1方法

20 

21         System.out.println("----------");

22         // public void method(String s)

23         Method m2 = c.getMethod("method", String.class);

24         m2.invoke(obj, "hello");

25         System.out.println("----------");

26 

27         // public String getString(String s, int i)

28         Method m3 = c.getMethod("getString", String.class, int.class);

29         Object objString = m3.invoke(obj, "hello", 100);

30         System.out.println(objString);

31         // String s = (String)m3.invoke(obj, "hello",100);

32         // System.out.println(s);

33         System.out.println("----------");

34 

35         // private void function()

36         Method m4 = c.getDeclaredMethod("function");

37         m4.setAccessible(true);

38         m4.invoke(obj);

39     }

40 }

 

27.11  反射_通过反射运行配置文件内容

通过配置文件运行类中的方法

反射:需要有配置文件配合使用。用class.txt代替。并且知道有两个键。className、methodName

例:

 1 public class Test

 2 {

 3     public static void main(String[] args) throws Exception 

 4     {

 5         // 反射前的做法

 6         // Student s = new Student();

 7         // s.love();

 8         // Teacher t = new Teacher();

 9         // t.love();

10         // Worker w = new Worker();

11         // w.love();

12         

13         // 反射后的做法

14         // 加载键值对数据

15         Properties prop = new Properties();

16         FileReader fr = new FileReader("class.txt");

17         prop.load(fr);

18         fr.close();

19 

20         // 获取数据

21         String className = prop.getProperty("className");

22         String methodName = prop.getProperty("methodName");

23 

24         // 反射

25         Class c = Class.forName(className);

26 

27         Constructor con = c.getConstructor();

28         Object obj = con.newInstance();

29 

30         // 调用方法

31         Method m = c.getMethod(methodName);

32         m.invoke(obj);

33     }

34 }

 

上例中,如果需要运行其他的类只需要修改class.txt文件中的内容即可

27.12  反射_通过反射越过泛型检查

实现向ArrayList<Integer>中添加一个字符串数据

 1 public class ArrayListDemo 

 2 {

 3     public static void main(String[] args) throws Exception

 4     {

 5         // 创建集合对象

 6         ArrayList<Integer> array = new ArrayList<Integer>();

 7 

 8         // array.add("hello");

 9         // array.add(10);

10 

11         Class c = array.getClass(); // 集合ArrayList的class文件对象

12         Method m = c.getMethod("add", Object.class);

13 

14         m.invoke(array, "hello"); // 调用array的add方法,传入的值是hello

15         m.invoke(array, "world");

16         m.invoke(array, "java");

17 

18         System.out.println(array);

19     }

20 }

 

27.13  反射_通过反射写一个通用的设置某个对象的某个属性为指定的值

 1 public class Tool 

 2 {

 3     public void setProperty(Object obj, String propertyName, Object value)throws Exception

 4     {

 5         // 根据对象获取字节码文件对象

 6         Class c = obj.getClass();

 7         // 获取该对象的propertyName成员变量

 8         Field field = c.getDeclaredField(propertyName);

 9         // 取消访问检查

10         field.setAccessible(true);

11         // 给对象的成员变量赋值为指定的值

12         field.set(obj, value);

13     }

14 }

15 

16 //测试类

17 public class ToolDemo 

18 {

19     public static void main(String[] args) throws Exception 

20     {

21         Person p = new Person();

22         Tool t = new Tool();

23         t.setProperty(p, "name", "小明");

24         t.setProperty(p, "age", 27);

25         System.out.println(p);

26         System.out.println("-----------");

27 

28         Dog d = new Dog();

29 

30         t.setProperty(d, "sex", '男');

31         t.setProperty(d, "price", 12.34f);

32 

33         System.out.println(d);

34     }

35 }

36 

37 class Dog

38 {

39     char sex;

40     float price;

41 

42     @Override

43     public String toString() 

44     {

45         return sex + "---" + price;

46     }

47 }

48 

49 class Person 

50 {

51     private String name;

52     public int age;

53 

54     @Override

55     public String toString()

56     {

57         return name + "---" + age;

58     }

59 }

 

27.14  反射_动态代理的概述和实现

动态代理:在程序运行过程中产生的这个对象,而程序运行过程中产生对象其实就是我们刚才反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理

 

在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib

 

Proxy类中的方法创建动态代理类对象

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,

     InvocationHandler h)throws IllegalArgumentException

返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。最终会调用InvocationHandler的方法

接口 InvocationHandler中的方法

Object invoke(Object proxy,Method method,Object[] args) throws Throwable

在代理实例上处理方法调用并返回结果。

 

Proxy.newProxyInstance

创建的代理对象是在jvm运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,

也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,

以$开头,proxy为中,最后一个数字表示对象的标号。

System.out.println(u.getClass().getName());

 

每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的invoke 方法来进行调用。

 

Proxy类中创建动态代理对象的方法的三个参数:

ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载

Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了

InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

 

 

InvocationHandler接口中invoke方法的三个参数:

proxy:代表动态代理对象

method:代表正在执行的方法

args:代表调用目标方法时传入的实参

27.15  设计模式_模版设计模式概述和使用

模版设计模式概述:模版方法模式就是定义一个算法的骨架,而将具体的算法延迟到子类中来实现

优点:使用模版方法模式,在定义算法骨架的同时,可以很灵活的实现具体的算法,满足用户灵活多变的需求

缺点:如果算法骨架有修改的话,则需要修改抽象类

例:

 1 //模板

 2 public abstract class GetTime 

 3 {

 4     // 计算出一段代码的运行时间

 5     public long getTime()

 6     {

 7         long start = System.currentTimeMillis();

 8         code();

 9 

10         long end = System.currentTimeMillis();

11 

12         return end - start;

13     }

14     public abstract void code();

15 }

16 

17 //实现类

18 public class ForDemo extends GetTime

19 {

20     @Override

21     public void code() 

22     {

23         for (int x = 0; x < 100000; x++) 

24         {

25             System.out.println(x);

26         }

27     }

28 }

29 //测试类

30 public class Practice 

31 {

32     public static void main(String[] args)

33     {

34         GetTime gt = new ForDemo();

35         System.out.println(gt.getTime() + "毫秒");

36     }

37 }

 

27.16  设计模式_装饰模式概述和使用

装饰设计模式概述:装饰模式就是使用被装饰类的一个子类的实例,在客户端将这个子类的实例交给装饰类。是继承的替代方案

优点:使用装饰模式,可以提供比继承更灵活的扩展对象的功能,它可以动态的添加对象的功能,并且可以随意的组合这些功能

缺点:正因为可以随意组合,所以就可能出现一些不合理的逻辑

例:

 1 public class Practice 

 2 {

 3     public static void main(String[] args)

 4     {

 5         Person p = new Person();

 6 //        p.chifan();

 7         

 8         NewPerson p1 = new NewPerson(p);

 9         p1.chifan();

10         

11         NewPerson2 p2 = new NewPerson2();

12         p2.chifan();

13     }

14 }

15 

16 class Person

17 {

18     void chifan()

19     {

20         System.out.println("吃饭");

21     }

22 }

23 

24 //这个类的出现是为了增强Person而出现的。

25 class NewPerson//装饰设计模式

26 {

27     private Person p ;

28     NewPerson(Person p)

29     {

30         this.p = p;

31     }

32     

33     public void chifan()

34     {

35         System.out.println("开胃酒");

36         p.chifan();

37         System.out.println("甜点");

38     }

39 

40 }

41 

42 

43 class NewPerson2 extends Person//继承

44 {

45     public void chifan()

46     {

47         System.out.println("开胃酒");

48         super.chifan();

49         System.out.println("甜点");

50     }

51 }

 

27.17  JDK5新特性_JDK5新特性回顾

自动装箱和拆箱、泛型、增强for循环、静态导入、可变参数

27.18  JDK5新特性_自己实现枚举类

枚举概述:是指将变量的值一一列出来,变量的值只限于列举出来的值的范围内。

举例:一周只有7天,一年只有12个月等。

单例设计模式:单例类是一个类只有一个实例

那么多例类就是一个类有多个实例,但不是无限个数的实例,而是有限个数的实例。这才能是枚举类。

 

例:

  1 //版本1

  2 public class Direction 

  3 {

  4     // 创建几个实例

  5     public static final Direction FRONT = new Direction();

  6     public static final Direction BEHIND = new Direction();

  7     public static final Direction LEFT = new Direction();

  8     public static final Direction RIGHT = new Direction();

  9 

 10     // 构造私有,不能无限的创建

 11     private Direction() 

 12     {}

 13 }

 14 ----------------------------------------------------------------------

 15 //版本2

 16 public class Direction2 

 17 {

 18     // 创建几个实例

 19     public static final Direction2 FRONT = new Direction2("前");

 20     public static final Direction2 BEHIND = new Direction2("后");

 21     public static final Direction2 LEFT = new Direction2("左");

 22     public static final Direction2 RIGHT = new Direction2("右");

 23     

 24     // 构造私有,别人就不能无限的创建了

 25     // private Direction2() {

 26     // }

 27     

 28     // 加入成员变量,并去掉无参构造

 29     private String name;

 30     

 31     private Direction2(String name) 

 32     {

 33         this.name = name;

 34     }

 35     

 36     public String getName() 

 37     {

 38         return name;

 39     }

 40 }

 41 ----------------------------------------------------------------------

 42 //版本3

 43 public abstract class Direction3 

 44 {

 45     // 创建几个实例

 46     public static final Direction3 FRONT = new Direction3("前") 

 47     {

 48         @Override

 49         public void show() 

 50         {

 51             System.out.println("前");

 52         }

 53 

 54     };

 55     public static final Direction3 BEHIND = new Direction3("后") 

 56     {

 57         @Override

 58         public void show() 

 59         {

 60             System.out.println("后");

 61         }

 62 

 63     };

 64     public static final Direction3 LEFT = new Direction3("左") 

 65     {

 66         @Override

 67         public void show()

 68         {

 69             System.out.println("左");

 70         }

 71 

 72     };

 73     public static final Direction3 RIGHT = new Direction3("右") 

 74     {

 75         @Override

 76         public void show() 

 77         {

 78             System.out.println("右");

 79         }

 80 

 81     };

 82 

 83     // 构造私有,别人就不能无限的创建了

 84     // private Direction2() {

 85     // }

 86 

 87     // 加入成员变量,并去掉无参构造

 88     private String name;

 89 

 90     private Direction3(String name) 

 91     {

 92         this.name = name;

 93     }

 94 

 95     public String getName() 

 96     {

 97         return name;

 98     }

 99 

100     // 加入抽象方法

101     public abstract void show();

102 }

103 ----------------------------------------------------------------------

104 //测试

105 public class DirectionDemo 

106 {

107     public static void main(String[] args) 

108     {

109         Direction d = Direction.FRONT;

110         System.out.println(d); // cn.itcast_01.Direction@175078b

111         System.out.println("------------------------------------");

112         Direction2 d2 = Direction2.FRONT;

113         System.out.println(d2);// cn.itcast_01.Direction2@11563ff

114         System.out.println(d2.getName());

115         d2 = Direction2.RIGHT;

116         System.out.println(d2);

117         System.out.println(d2.getName());

118         System.out.println("------------------------------------");

119         Direction3 d3 = Direction3.FRONT;

120         System.out.println(d3);

121         System.out.println(d3.getName());

122         d3.show();

123 

124         d3 = Direction3.LEFT;

125         System.out.println(d3);

126         System.out.println(d3.getName());

127         d3.show();

128     }

129 }

 

27.19  JDK5新特性_通过enum实现枚举类

格式:

只有枚举项的枚举类

public enum 枚举类名 

{

枚举项1,枚举项2,枚举项3…;

}

例:

  1 //版本1

  2 public enum Direction 

  3 {

  4     FRONT, BEHIND, LEFT, RIGHT;

  5 }

  6 ----------------------------------------------------------------------

  7 //版本2

  8 public enum Direction2 

  9 {

 10     FRONT("前"), BEHIND("后"), LEFT("左"), RIGHT("右");

 11 

 12     private String name;

 13 

 14     private Direction2(String name) 

 15     {

 16         this.name = name;

 17     }

 18 

 19     public String getName() 

 20     {

 21         return name;

 22     }

 23 }

 24 

 25 ----------------------------------------------------------------------

 26 //版本3

 27 public enum Direction3 

 28 {

 29     FRONT("前") 

 30     {

 31         @Override

 32         public void show() 

 33         {

 34             System.out.println("前");

 35         }

 36     },

 37     BEHIND("后") 

 38     {

 39         @Override

 40         public void show() 

 41         {

 42             System.out.println("后");

 43         }

 44     },

 45     LEFT("左") 

 46     {

 47         @Override

 48         public void show() 

 49         {

 50             System.out.println("左");

 51         }

 52     },

 53     RIGHT("右") 

 54     {

 55         @Override

 56         public void show() 

 57         {

 58             System.out.println("右");

 59         }

 60     };

 61 

 62     private String name;

 63 

 64     private Direction3(String name) 

 65     {

 66         this.name = name;

 67     }

 68 

 69     public String getName()

 70     {

 71         return name;

 72     }

 73 

 74     public abstract void show();

 75 }

 76 

 77 ----------------------------------------------------------------------

 78 //测试

 79 public class DirectionDemo 

 80 {

 81     public static void main(String[] args) 

 82     {

 83         Direction d = Direction.FRONT;

 84         System.out.println(d); // FRONT

 85         // public String toString()返回枚举常量的名称,它包含在声明中。

 86         System.out.println("-------------");

 87         Direction2 d2 = Direction2.FRONT;

 88         System.out.println(d2);

 89         System.out.println(d2.getName());

 90         System.out.println("-------------");

 91         Direction3 d3 = Direction3.FRONT;

 92         System.out.println(d3);

 93         System.out.println(d3.getName());

 94         d3.show();

 95         System.out.println("--------------");

 96 

 97         Direction3 dd = Direction3.FRONT;

 98         dd = Direction3.LEFT;

 99 

100         switch (dd) 

101         {

102             case FRONT:

103                 System.out.println("你选择了前");

104                 break;

105             case BEHIND:

106                 System.out.println("你选择了后");

107                 break;

108             case LEFT:

109                 System.out.println("你选择了左");

110                 break;

111             case RIGHT:

112                 System.out.println("你选择了右");

113                 break;

114         }

115     }

116 }

运行结果:

FRONT

-------------

FRONT

前

-------------

FRONT

前

前

--------------

你选择了左

27.20  JDK5新特性_枚举的注意事项

注意事项:

1.定义枚举类要用关键字enum

2.所有枚举类都是Enum的子类

3.枚举类的第一行上必须是枚举项,最后一个枚举项后的分号是可以省略的,但是如果枚举类有其他的东西,这个分号就不能省 略。建议不要省略

4.枚举类可以有构造器,但必须是private的,它默认的也是private的。枚举项的用法比较特殊:枚举(“”);

5.枚举类也可以有抽象方法,但是枚举项必须重写该方法

6.枚举在switch语句中的使用

27.21  JDK5新特性_枚举类的常见方法

1.public final int compareTo(E o)比较此枚举与指定对象的顺序。

2.public final String name()返回此枚举常量的名称,在其枚举声明中对其进行声明。

3.public final int ordinal()返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。 

4.public String toString()返回枚举常量的名称,它包含在声明中。

5.public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)

返回带指定名称的指定枚举类型的枚举常量。

 

例:

 1 public class Practice 

 2 {

 3     public static void main(String[] args)

 4     {

 5         // int compareTo(E o)

 6         Direction2 d21 = Direction2.FRONT;//0

 7         Direction2 d22 = Direction2.BEHIND;//1

 8         Direction2 d23 = Direction2.LEFT;//2

 9         Direction2 d24 = Direction2.RIGHT;//3

10         System.out.println(d21.compareTo(d21));//0

11         System.out.println(d21.compareTo(d24));//-3

12         System.out.println(d24.compareTo(d21));//3

13         System.out.println("---------------");

14         // String name()

15         System.out.println(d21.name());//FRONT

16         System.out.println("--------------");

17         // int ordinal()

18         System.out.println(d21.ordinal());//0

19         System.out.println(d22.ordinal());//1

20         System.out.println("--------------");

21         // String toString()

22         System.out.println(d21.toString());//FRONT

23         System.out.println(d22.toString());//BEHIND

24         System.out.println("--------------");

25         // <T> T valueOf(Class<T> type,String name)

26         Direction2 d = Enum.valueOf(Direction2.class, "FRONT");

27         System.out.println(d.getName());//

28         System.out.println("----------------");

29         // values()

30         // 此方法虽然在JDK文档中查找不到,但每个枚举类都具有该方法,它遍历枚举类的所有枚举值非常方便

31         Direction2[] dirs = Direction2.values();

32         for (Direction2 d2 : dirs) 

33         {

34             System.out.println(d2);

35             System.out.println(d2.getName());

36         }

37     }

38 }

 

27.22  JDK7新特性_JDK7的六个新特性回顾和讲解

二进制字面量

JDK7开始,可以用二进制来表示整数(byte,short,int和long)。

使用二进制字面量的好处是,可以使代码更容易被理解。语法非常简单,只要在二进制数值前面加 0b或者0B

例:int x = 0b110110

数字字面量可以出现下划线

为了增强对数值的阅读性,如我们经常把数据用逗号分隔一样。JDK7提供了_对数据分隔。

例:int x = 100_1000;

注意事项:

不能出现在进制标识和数值之间

不能出现在数值开头和结尾

不能出现在小数点旁边

switch 语句可以用字符串

泛型简化

异常的多个catch合并

try-with-resources 语句

try(必须是java.lang.AutoCloseable的子类对象){…}

好处:

资源自动释放,不需要close()了

把需要关闭资源的部分都定义在这里就行了

主要是流体系的对象是这个接口的子类(JDK7的API)

27.23  JDK8新特性_接口中也可以有方法

例:

 1 interface Inter

 2 {

 3         //抽象方法

 4         public abstract void show();

 5         

 6         //default方法

 7         public default void defaultPrint() 

 8         {

 9             System.out.println("defaultPrint run");

10         }

11 

12         //static方法

13         public static void staticPrint()

14         {

15             System.out.println("staticPrint run");

16         }

17 }

18 

19 //实现类

20 class InterImpl implements Inter

21 {

22         public void show()

23         {

24             System.out.println("重写接口中的方法");

25         }

26 }

27 

28 //测试类

29 public class Demo

30 {

31         public static void main(String[] args) 

32         {

33             //Inter.defaultPrint();     //非静态方法不能直接使用 

34             Inter.staticPrint();

35             

36             Inter i = new InterImpl();

37             i.defaultPrint();

38             i.show();

39         }

40 }

你可能感兴趣的:(JavaSE)