反射

  • 反射概述
    • 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();
    }
}