反射 反射概述 Java的反射机制是在运行状态中, 对于任意一个类, 都能知道这个类的所有属性和方法 对于任意一个对象, 都能够调用它的任意一个方法和属性 这种动态获取信息以及动态调用对象的方法的功能称为Java语文的反射机制 想要解剖一个类, 必需先要获取到该类的字节码文件对象 而解剖使用的就是Class类中的方法, 所以先要获取到每一个字节码文件对应的Class类型的对象 反射的三种方式 Object烦的getClass()方法, 判断2个对象是否是同一个字节码文件 静态属性class, 锁对象(Person.class) Class类中静态方法forName(), 读取配置文件 import com.lizicai.bean.Person; public class Demo1_Reflect { public static void main(String[] args) throws ClassNotFoundException { Class clazz1 = Class.forName("com.lizicai.bean.Person"); Class clazz2 = Person.class; Person p = new Person(); Class clazz3 = p.getClass(); System.out.println(clazz1 == clazz2); System.out.println(clazz2 == clazz3); } } 反射(Class.forName()读取配置文件举例) import java.io.*; public class Demo2_Reflect { public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { // nouseReflect(); String str = null; BufferedReader br = new BufferedReader(new FileReader("config.properties")); str = br.readLine(); Class clazz = Class.forName(str); Fruit f = (Fruit) clazz.newInstance(); Juier j = new Juier(); j.run(f); } private static void nouseReflect() { Juier j = new Juier(); Apple apple = new Apple(); j.run(apple); j.run(new Orange()); } } interface Fruit{ public void squeeze(); } class Apple implements Fruit { @Override public void squeeze(){ System.out.println("苹果汁"); } } class Orange implements Fruit{ @Override public void squeeze(){ System.out.println("橙汁"); } } class Juier{ public void run(Fruit fruit){ fruit.squeeze(); } public void run(Orange orange){ orange.squeeze(); } } com.lizicai.reflect.Orange 通过反射获取带参构造方法并使用 构造函数必须public, 否则报NoSuchMethodException 异常. import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class Demo3_Reflect { public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { Class clazz = Class.forName("com.lizicai.bean.Person"); // Person p = (Person) clazz.newInstance(); Constructor c = clazz.getConstructor(String.class, int.class); Person p = (Person) c.newInstance("张三",23); System.out.println(p); } } public class Person { private String name; private int age; public Person(String name, int age){ this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public boolean equals(Object obj) { return super.equals(obj); } @Override public int hashCode() { return super.hashCode(); } @Override public String toString() { return this.getName() + this.getAge(); } } 通过反射获取成员变量并使用 import com.lizicai.bean.Person; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; public class Demo4_Reflect { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException { Class clazz = Class.forName("com.lizicai.bean.Person"); Constructor c = clazz.getConstructor(String.class, int.class); Person p = (Person) c.newInstance("张三",23); // Field f = clazz.getField("name"); // 暴力反射 Field f = clazz.getDeclaredField("name"); // 去除私有权限 f.setAccessible(true); f.set(p,"李四"); System.out.println(p); } } 通过反射获取方法并使用 import com.lizicai.bean.Person; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Demo5_Reflect { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, NoSuchFieldException, InvocationTargetException { Class clazz = Class.forName("com.lizicai.bean.Person"); Constructor c = clazz.getConstructor(String.class, int.class); Person p = (Person) c.newInstance("张三",23); Method m = clazz.getMethod("eat"); m.invoke(p); Method m2 = clazz.getMethod("eat", int.class); m2.invoke(p,10); } } 通过反射越过泛型检查 泛型编译时检查, 运行时没有检查 import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; public class Test1 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { ArrayList<Integer> list = new ArrayList<>(); list.add(1); list.add(2); Class clazz = Class.forName("java.util.ArrayList"); Method m = clazz.getMethod("add",Object.class); m.invoke(list,"test"); System.out.println(list); } } 通过反射写一个通用的设置某个对象的某个属性为指定的值 Person对象仍然是上面的 import java.lang.reflect.Field; public class Tool { public void setProperty(Object obj, String propertyName, Object value) throws NoSuchFieldException, IllegalAccessException { Class clazz = obj.getClass(); Field f = clazz.getDeclaredField(propertyName); f.setAccessible(true); f.set(obj,value); } } import com.lizicai.bean.Person; public class Test2 { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { Person p = new Person("小明",23); System.out.println(p); Tool t = new Tool(); t.setProperty(p,"name","小红"); System.out.println(p); } } 练习 import java.io.*; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class Test3 { public static void main(String[] args) throws IOException, ClassNotFoundException, InvocationTargetException, IllegalAccessException, NoSuchMethodException, InstantiationException { File file = new File("demo.properties"); BufferedReader br = new BufferedReader(new FileReader(file)); String clazzName = br.readLine(); br.close(); Class clazz = Class.forName(clazzName); DemoClass dc = (DemoClass) clazz.newInstance(); Method m = clazz.getMethod("run"); m.invoke(dc); } } public class DemoClass { public void run(){ System.out.println("大王叫我来巡山"); } } com.lizicai.test.DemoClass 动态代理的概述和实现 写好了代理, 就能在所有类前后进行一些处理 public interface User { public void add(); public void delete(); } public class UserImp implements User{ @Override public void add() { // System.out.println("权限校验"); System.out.println("添加"); // System.out.println("日志记录"); } @Override public void delete() { // System.out.println("权限校验"); System.out.println("删除"); // System.out.println("日志记录"); } } import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler(Object target){ this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("权限检验"); method.invoke(target,args); System.out.println("日志记录"); return null; } } import java.lang.reflect.Proxy; public class Test { public static void main(String[] args) { User ui = new UserImp(); ui.add(); ui.delete(); MyInvocationHandler m = new MyInvocationHandler(ui); User u = (User) Proxy.newProxyInstance(ui.getClass().getClassLoader(), ui.getClass().getInterfaces(),m); u.add(); u.delete(); } } 模版(Template)设计模式概述和使用 模版设计模式概述 模版方法模式就是定义一个算法模版, 而将具体的算法延迟到子类中实现 优点 缺点 使用模版方法模式, 在定义骨架的同时, 可以很灵活实现具体的方法, 满足用户灵活多变的需求 如果算法有修改, 则需要修改抽象类 public class Demo1_Template extends TestTime{ public static void main(String[] args) { Demo1_Template d = new Demo1_Template(); System.out.println(d.getTime()); } @Override public void code() { for(int i=0;i<100000;i++){ System.out.println(i); } } } abstract class TestTime{ final public long getTime(){ long start = System.currentTimeMillis(); code(); long end = System.currentTimeMillis(); return end - start; } public abstract void code(); } 自己实现枚举类 概述 是指将变量的值一一列举出来, 变量的值仅限于列举出来的值的范围内 单例模式, 只有一个实例 多例类就是一个类有多个实例, 但不是无限多个实例, 是有限个数的实例, 这才是枚举类. 枚举类有下例3种形式 public class Week { final static Week MON = new Week(); final static Week TUE = new Week(); final static Week WED = new Week(); private Week(){} } public class Week2 { final static Week2 MON = new Week2("星期一"); final static Week2 TUE = new Week2("星期二"); final static Week2 WED = new Week2("星期三"); String name; private Week2(String name){ this.name = name; } @Override public String toString() { return this.name; } } public abstract class Week3 { final static Week3 MON = new Week3("星期一"){ @Override public void show() { System.out.println("星期一"); } }; final static Week3 TUE = new Week3("星期二"){ @Override public void show() { System.out.println("星期二"); } }; final static Week3 WED = new Week3("星期三") { @Override public void show() { System.out.println("星期三"); } }; String name; private Week3(String name){ this.name = name; } @Override public String toString() { return this.name; } public abstract void show(); } public class Demo1_Enum { public static void main(String[] args) { Week mon = Week.MON; System.out.println(mon); Week2 Mon = Week2.MON; Week2 Tue = Week2.TUE; Week2 Wed = Week2.WED; System.out.println(Mon); System.out.println(Tue); System.out.println(Wed); Week3 MON = Week3.MON; Week3 TUE = Week3.TUE; Week3 WED = Week3.WED; MON.show(); TUE.show(); WED.show(); } } 通过enum实现枚举类 public enum Week { MON,TUE,WED; } public enum Week2 { MON("星期一"),TUE("星期二"),WED("星期三"); private String name ; Week2(String name){ this.name = name; } public String getName() { return name; } } public enum Week3 { MON("星期一"){ @Override public void show() { System.out.println("星期一"); } },TUE("星期二"){ @Override public void show() { System.out.println("星期二"); } },WED("星期三"){ @Override public void show() { System.out.println("星期三"); } }; private String name ; Week3(String name){ this.name = name; } public String getName() { return name; } public abstract void show(); } public class Demo1_Enum { public static void main(String[] args) { Week mon = Week.MON; Week tue = Week.TUE; System.out.println(mon); System.out.println(tue); Week2 Mon = Week2.MON; Week2 Tue = Week2.TUE; System.out.println(Mon); System.out.println(Tue.getName()); Week3 MON = Week3.MON; Week3 TUE = Week3.TUE; Week3 WED = Week3.WED; System.out.println(MON); System.out.println(TUE.getName()); System.out.println(WED.getName()); } } switch 使用枚举 public static void demo1(){ Week2 MON = Week2.TUE; switch (MON){ case MON: System.out.println("星期一"); break; case TUE: System.out.println("星期二"); break; case WED: System.out.println("星期三"); break; } } 常用的枚举方法 public final int ordinal() 获取枚举的位置 public final int compareTo(E o) 比较枚举位置, 返回差 public final String name() 获取枚举实例的名字 public static <T extends Enum> T valueOf(Class enumType, String name) 字节码对象获取枚举项 values 获取枚举的数组 public class Demo2_Enum { public static void main(String[] args) { Week2 mon = Week2.MON; Week2 tue = Week2.TUE; Week2 wed = Week2.WED; System.out.println(mon.ordinal()); System.out.println(tue.ordinal()); System.out.println(wed.ordinal()); System.out.println(mon.compareTo(tue)); System.out.println(mon.compareTo(wed)); System.out.println(mon.name()); System.out.println(tue.name()); System.out.println(mon); System.out.println(tue.toString()); // 字节码对象获取枚举项 Week2 TUE = Week2.valueOf(Week2.class,"TUE"); System.out.println(TUE); Week2[] arr = Week2.values(); for(Week2 w:arr){ System.out.println(w); } } } JDK 1.7 新增内容 switch支持字符串 异常catch多个异常, 用|隔开 try-whith-resources 自动关流 import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class Demo3_AutoClose { public static void main(String[] args) { File file = new File("config.properties"); //资源放在try()中, 会自动关闭资源, 不用在finally 中关闭了 try ( FileInputStream fis = new FileInputStream(file)){ int b; while ( ( b = fis.read() ) != -1){ System.out.println(b); } } catch (IOException e){ System.out.println(e.getMessage()); } } } JDK 1.8 新增内容 接口可以支持default修饰, 有方法体 接口也可以有静态方法了 内部类可访问的变量默认是final修饰 public class Demo4_JKD18 { // JDK1.8新特性 public static void main(String[] args) { Demo d = new Demo(); d.show(); Inter.test(); d.run(); } } interface Inter{ public default void show(){ System.out.println("显示"); } public static void test(){ System.out.println("测试"); } } class Demo implements Inter{ public void run(){ // num 默认是final int num = 20; class Inner{ public void fun(){ System.out.println("fun"); } } Inner i = new Inner(); i.fun(); } }