关于java:Java基础学习第二十七天类加载器和反射

2次阅读

共计 13483 个字符,预计需要花费 34 分钟才能阅读完成。

类的加载

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

加载

就是指将 class 文件读入内存,并为之创立一个 Class 对象。
任何类被应用时零碎都会建设一个 Class 对象。
连贯
验证 是否有正确的内部结构,并和其余类协调一致
筹备 负责为类的动态成员分配内存,并设置默认初始化值
解析 将类的二进制数据中的符号援用替换为间接援用
初始化 就是咱们以前讲过的初始化步骤
类初始化机会
创立类的实例
拜访类的动态变量,或者为动态变量赋值
调用类的静态方法
应用反射形式来强制创立某个类或接口对应的 java.lang.Class 对象
初始化某个类的子类
间接应用 java.exe 命令来运行某个主类
类加载器
负责将.class 文件加载到内存中,并为之生成对应的 Class 对象。
尽管咱们不须要关怀类加载机制,然而理解这个机制咱们就能更好的了解程序的运行。
类加载器的组成
Bootstrap ClassLoader 根类加载器
Extension ClassLoader 扩大类加载器
Sysetm ClassLoader 零碎类加载器
类加载器的作用
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 包和类门路

反射

JAVA 反射机制是在运行状态中,对于任意一个类,都可能晓得这个类的所有属性和办法;对于任意一个对象,都可能调用它的任意一个办法和属性;这种动静获取的信息以及动静调用对象的办法的性能称为 java 语言的反射机制。
要想解剖一个类, 必须先要获取到该类的字节码文件对象。而解剖应用的就是 Class 类中的办法。所以先要获取到每一个字节码文件对应的 Class 类型的对象。
通过反射获取构造方法并应用
获取构造方法
getConstructors
getDeclaredConstructors
创建对象
newInstance()
con.newInstance(“zhangsan”, 20);
获取所有成员
getFields,getDeclaredFields
获取单个成员
getField,getDeclaredField
批改成员的值
set(Object obj,Object value)
将指定对象变量上此 Field 对象示意的字段设置为指定的新值。
获取所有办法
getMethods
getDeclaredMethods
获取单个办法
getMethod
getDeclaredMethod
暴力拜访

method.setAccessible(true);

获取 class 文件对象的形式:

A:Object 类的 getClass()办法
B: 数据类型的动态属性 class
C:Class 类中的静态方法
public static Class forName(String className)
个别咱们应用谁呢?

A: 本人玩 任选一种,第二种比拟不便
B: 开发 第三种
为什么呢? 因为第三种是一个字符串,而不是一个具体的类名。这样咱们就能够把这样的字符串配置到配置文件中。
通过反射获取无参构造方法并应用

/*
 * 反射:就是通过 class 文件对象,去应用该文件中的成员变量,构造方法,成员办法。* Class 类:*      成员变量    Field
 *      构造方法    Constructor
 *      成员办法    Method
 * 
 */
public class ReflectDemo {public static void main(String[] args) throws ClassNotFoundException {
        // 形式 1
        Person p = new Person();
        Class c = p.getClass();

        Person p2 = new Person();
        Class c2 = p2.getClass();

        System.out.println(p == p2);// false
        System.out.println(c == c2);// true

        // 形式 2
        Class c3 = Person.class;
        // int.class;
        // String.class;
        System.out.println(c == c3);

        // 形式 3
        // ClassNotFoundException
        Class c4 = Class.forName("cn.itcast_01.Person");
        System.out.println(c == c4);
    }
}

public class Person {
    private String name;
    int age;
    public String address;

    public Person() {}

    private Person(String name) {this.name = name;}

    Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public void show() {System.out.println("show");
    }

    public void method(String s) {System.out.println("method" + s);
    }

    public String getString(String s, int i) {return s + "---" + i;}

    private void function() {System.out.println("function");
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", address=" + address
                + "]";
    }

} 

通过反射获取无参构造方法的应用

/*
 * 通过反射获取构造方法并应用。*/
public class ReflectDemo {public static void main(String[] args) throws Exception {
        // 获取字节码文件对象
        Class c = Class.forName("cn.itcast_01.Person");

        // 获取构造方法
        // public Constructor[] getConstructors(): 所有公共构造方法
        // public Constructor[] getDeclaredConstructors(): 所有构造方法
        // Constructor[] cons = c.getDeclaredConstructors();
        // for (Constructor con : cons) {// System.out.println(con);
        // }

        // 获取单个构造方法
        // public Constructor<T> getConstructor(Class<?>... parameterTypes)
        // 参数示意的是:你要获取的构造方法的结构参数个数及数据类型的 class 字节码文件对象
        Constructor con = c.getConstructor();// 返回的是构造方法对象

        // Person p = new Person();
        // System.out.println(p);
        // public T newInstance(Object... initargs)
        // 应用此 Constructor 对象示意的构造方法来创立该构造方法的申明类的新实例,并用指定的初始化参数初始化该实例。Object obj = con.newInstance();
        System.out.println(obj);

        // Person p = (Person)obj;
        // p.show();}
} 

获取带参构造方法

/*
 * 需要:通过反射去获取该构造方法并应用:* public Person(String name, int age, String address)
 * 
 * Person p = new Person("林青霞",27,"北京");
 * System.out.println(p);
 */

public class ReflectDemo2 {public static void main(String[] args) throws Exception {
        // 获取字节码文件对象
        Class c = Class.forName("cn.itcast_01.Person");

        // 获取带参构造方法对象
        // public Constructor<T> getConstructor(Class<?>... parameterTypes)
        Constructor con = c.getConstructor(String.class, int.class,
                String.class);

        // 通过带参构造方法对象创建对象
        // public T newInstance(Object... initargs)
        Object obj = con.newInstance("林青霞", 27, "北京");

        System.out.println(obj);
    }
} 

获取公有构造方法并应用

/*
 * 需要:通过反射获取公有构造方法并应用
 * private Person(String name){}
 * 
 * Person p = new Person("风清扬");
 * System.out.println(p);
 */
public class ReflectDemo3 {public static void main(String[] args) throws Exception {
        // 获取字节码文件对象
        Class c = Class.forName("cn.itcast_01.Person");

        // 获取公有构造方法对象
        // NoSuchMethodException:每有这个办法异样
        // 起因是一开始咱们应用的办法只能获取公共的,上面这种形式就能够了。Constructor con = c.getDeclaredConstructor(String.class);

        // 用该公有构造方法创建对象
        // IllegalAccessException: 非法的拜访异样。// 暴力拜访
        con.setAccessible(true);// 值为 true 则批示反射的对象在应用时应该勾销 Java 语言拜访查看。Object obj = con.newInstance("风清扬");

        System.out.println(obj);
    }
} 

获取成员变量并应用

/*
 * 通过反射获取成员变量并应用
 */
public class ReflectDemo {public static void main(String[] args) throws Exception {
        // 获取字节码文件对象
        Class c = Class.forName("cn.itcast_01.Person");

        // 获取所有的成员变量
        // Field[] fields = c.getFields();
        // Field[] fields = c.getDeclaredFields();
        // for (Field field : fields) {// System.out.println(field);
        // }

        /*
         * Person p = new Person(); p.address = "北京"; System.out.println(p);
         */

        // 通过无参构造方法创建对象
        Constructor con = c.getConstructor();
        Object obj = con.newInstance();
        System.out.println(obj);

        // 获取单个的成员变量
        // 获取 address 并对其赋值
        Field addressField = c.getField("address");
        // public void set(Object obj,Object value)
        // 将指定对象变量上此 Field 对象示意的字段设置为指定的新值。addressField.set(obj, "北京"); // 给 obj 对象的 addressField 字段设置值为 "北京"
        System.out.println(obj);

        // 获取 name 并对其赋值
        // NoSuchFieldException
        Field nameField = c.getDeclaredField("name");
        // IllegalAccessException
        nameField.setAccessible(true);
        nameField.set(obj, "林青霞");
        System.out.println(obj);

        // 获取 age 并对其赋值
        Field ageField = c.getDeclaredField("age");
        ageField.setAccessible(true);
        ageField.set(obj, 27);
        System.out.println(obj);
    }
} 

获取无参无返回值成员办法并应用

获取带参数返回值成员办法并应用

public class ReflectDemo {public static void main(String[] args) throws Exception {
        // 获取字节码文件对象
        Class c = Class.forName("cn.itcast_01.Person");

        // 获取所有的办法
        // Method[] methods = c.getMethods(); // 获取本人的包含父亲的公共办法
        // Method[] methods = c.getDeclaredMethods(); // 获取本人的所有的办法
        // for (Method method : methods) {// System.out.println(method);
        // }

        Constructor con = c.getConstructor();
        Object obj = con.newInstance();

        /*
         * Person p = new Person(); p.show();
         */

        // 获取单个办法并应用
        // public void show()
        // public Method getMethod(String name,Class<?>... parameterTypes)
        // 第一个参数示意的办法名,第二个参数示意的是办法的参数的 class 类型
        Method m1 = c.getMethod("show");
        // obj.m1(); // 谬误
        // public Object invoke(Object obj,Object... args)
        // 返回值是 Object 接管, 第一个参数示意对象是谁,第二参数示意调用该办法的理论参数
        m1.invoke(obj); // 调用 obj 对象的 m1 办法

        System.out.println("----------");
        // public void method(String s)
        Method m2 = c.getMethod("method", String.class);
        m2.invoke(obj, "hello");
        System.out.println("----------");

        // public String getString(String s, int i)
        Method m3 = c.getMethod("getString", String.class, int.class);
        Object objString = m3.invoke(obj, "hello", 100);
        System.out.println(objString);
        // String s = (String)m3.invoke(obj, "hello",100);
        // System.out.println(s);
        System.out.println("----------");

        // private void function()
        Method m4 = c.getDeclaredMethod("function");
        m4.setAccessible(true);
        m4.invoke(obj);
    }
} 

反射利用举例

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

public class Student {public void love() {System.out.println("爱生存, 爱 Java");
    }
}

public class Teacher {public void love() {System.out.println("爱生存, 爱青霞");
    }
}

public class Worker {public void love() {System.out.println("爱生存, 爱老婆");
    }
}

/*
 * 通过配置文件运行类中的办法
 * 
 * 反射:*      须要有配置文件配合应用。*      用 class.txt 代替。*      并且你晓得有两个键。*          className
 *          methodName
 */
public class Test {public static void main(String[] args) throws Exception {
        // 反射前的做法
        // Student s = new Student();
        // s.love();
        // Teacher t = new Teacher();
        // t.love();
        // Worker w = new Worker();
        // w.love();
        // 反射后的做法

        // 加载键值对数据
        Properties prop = new Properties();
        FileReader fr = new FileReader("class.txt");
        prop.load(fr);
        fr.close();

        // 获取数据
        String className = prop.getProperty("className");
        String methodName = prop.getProperty("methodName");

        // 反射
        Class c = Class.forName(className);

        Constructor con = c.getConstructor();
        Object obj = con.newInstance();

        // 调用办法
        Method m = c.getMethod(methodName);
        m.invoke(obj);
    }
} 

我给你 ArrayList 的一个对象,我想在这个汇合中增加一个字符串数据,如何实现呢?

public class ArrayListDemo {public static void main(String[] args) throws NoSuchMethodException,
            SecurityException, IllegalAccessException,
            IllegalArgumentException, InvocationTargetException {
        // 创立汇合对象
        ArrayList<Integer> array = new ArrayList<Integer>();

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

        Class c = array.getClass(); // 汇合 ArrayList 的 class 文件对象
        Method m = c.getMethod("add", Object.class);

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

        System.out.println(array);
    }
} 

写一个办法,
public void setProperty(Object obj, String propertyName, Object value){},
此办法可将 obj 对象中名为 propertyName 的属性的值设置为 value。

public class Tool {public void setProperty(Object obj, String propertyName, Object value)
            throws NoSuchFieldException, SecurityException,
            IllegalArgumentException, IllegalAccessException {
        // 依据对象获取字节码文件对象
        Class c = obj.getClass();
        // 获取该对象的 propertyName 成员变量
        Field field = c.getDeclaredField(propertyName);
        // 勾销拜访查看
        field.setAccessible(true);
        // 给对象的成员变量赋值为指定的值
        field.set(obj, value);
    }
}

public class ToolDemo {public static void main(String[] args) throws NoSuchFieldException,
            SecurityException, IllegalArgumentException, IllegalAccessException {Person p = new Person();
        Tool t = new Tool();
        t.setProperty(p, "name", "林青霞");
        t.setProperty(p, "age", 27);
        System.out.println(p);
        System.out.println("-----------");

        Dog d = new Dog();

        t.setProperty(d, "sex", '男');
        t.setProperty(d, "price", 12.34f);

        System.out.println(d);
    }
}

class Dog {
    char sex;
    float price;

    @Override
    public String toString() {return sex + "---" + price;}
}

class Person {
    private String name;
    public int age;

    @Override
    public String toString() {return name + "---" + age;}
} 

动静代理

代理:原本应该本人做的事件,却请了他人来做,被请的人就是代理对象。
举例:秋季回家买票让人代买
动静代理:在程序运行过程中产生的这个对象

而程序运行过程中产生对象其实就是咱们方才反射解说的内容,所以,动静代理其实就是通过反射来生成一个代理。
在 Java 中 java.lang.reflect 包下提供了一个 Proxy 类和一个 InvocationHandler 接口,通过应用这个类和接口就能够生成动静代理对象。JDK 提供的代理只能针对接口做代理。咱们有更弱小的代理 cglib。

Proxy 类中的办法创立动静代理类对象

public static Object newProxyInstance(ClassLoader loader,Class
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("权限校验");
        Object result = method.invoke(target, args);
        System.out.println("日志记录");
        return result; // 返回的是代理对象
    }
}

public interface StudentDao {public abstract void login();

    public abstract void regist();}

public class StudentDaoImpl implements StudentDao {

    @Override
    public void login() {System.out.println("登录性能");
    }

    @Override
    public void regist() {System.out.println("注册性能");
    }

}

/*
 * 用户操作接口
 */
public interface UserDao {public abstract void add();

    public abstract void delete();

    public abstract void update();

    public abstract void find();}

public class UserDaoImpl implements UserDao {

    @Override
    public void add() {System.out.println("增加性能");
    }

    @Override
    public void delete() {System.out.println("删除性能");
    }

    @Override
    public void update() {System.out.println("批改性能");
    }

    @Override
    public void find() {System.out.println("查找性能");
    }

}

public class Test {public static void main(String[] args) {UserDao ud = new UserDaoImpl();
        ud.add();
        ud.delete();
        ud.update();
        ud.find();
        System.out.println("-----------");
        // 咱们要创立一个动静代理对象
        // 我筹备对 ud 对象做一个代理对象
        MyInvocationHandler handler = new MyInvocationHandler(ud);
        UserDao proxy = (UserDao) Proxy.newProxyInstance(ud.getClass()
                .getClassLoader(), ud.getClass().getInterfaces(), handler);
        proxy.add();
        proxy.delete();
        proxy.update();
        proxy.find();
        System.out.println("-----------");

        StudentDao sd = new StudentDaoImpl();
        MyInvocationHandler handler2 = new MyInvocationHandler(sd);
        StudentDao proxy2 = (StudentDao) Proxy.newProxyInstance(sd.getClass()
                .getClassLoader(), sd.getClass().getInterfaces(), handler2);
        proxy2.login();
        proxy2.regist();}
} 

模版设计模式(抽象类)

模版办法模式就是定义一个算法的骨架,而将具体的算法提早到子类中来实现
长处
应用模版办法模式,在定义算法骨架的同时,能够很灵便的实现具体的算法,满足用户灵便多变的需要
毛病
如果算法骨架有批改的话,则须要批改抽象类
p

ublic class ForDemo extends GetTime {

    @Override
    public void code() {for (int x = 0; x < 100000; x++) {System.out.println(x);
        }
    }

}

public abstract class GetTime {
    // 需要:请给我计算出一段代码的运行工夫
    public long getTime() {long start = System.currentTimeMillis();
        code();

        long end = System.currentTimeMillis();

        return end - start;
    }

    public abstract void code();}

public class GetTimeDemo {public static void main(String[] args) {// GetTime gt = new GetTime();
        // System.out.println(gt.getTime() + "毫秒");

        GetTime gt = new ForDemo();
        System.out.println(gt.getTime() + "毫秒");

        gt = new IODemo();
        System.out.println(gt.getTime() + "毫秒");
    }
}

public class IODemo extends GetTime{

    @Override
    public void code() {
        try {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.avi"));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.avi"));
            byte[] bys = new byte[1024];
            int len = 0;
            while ((len = bis.read(bys)) != -1) {bos.write(bys, 0, len);
            }
            bos.close();
            bis.close();} catch (IOException e) {e.printStackTrace();
        }
    }

} 

装璜设计模式

装璜模式就是应用被装璜类的一个子类的实例,在客户端将这个子类的实例交给装璜类。是继承的代替计划
长处
应用装璜模式,能够提供比继承更灵便的扩大对象的性能,它能够动静的增加对象的性能,并且能够随便的组合这些性能
毛病
正因为能够随便组合,所以就可能呈现一些不合理的逻辑

public interface Phone {public abstract void call();
}

public class IPhone implements Phone {

    @Override
    public void call() {System.out.println("手机能够打电话了");
    }

}

public class MusicPhoneDecorate extends PhoneDecorate {public MusicPhoneDecorate(Phone p) {super(p);
    }

    @Override
    public void call() {super.call();
        System.out.println("手机能够听音乐");
    }
}

public class RingPhoneDecorate extends PhoneDecorate {public RingPhoneDecorate(Phone p) {super(p);
    }

    @Override
    public void call() {System.out.println("手机能够听彩铃");
        super.call();}
}

public abstract class PhoneDecorate implements Phone {

    private Phone p;

    public PhoneDecorate(Phone p) {this.p = p;}

    @Override
    public void call() {this.p.call();
    }
}

public class PhoneDemo {public static void main(String[] args) {Phone p = new IPhone();
        p.call();
        System.out.println("------------");

        // 需要:我想在接电话前,听彩铃
        PhoneDecorate pd = new RingPhoneDecorate(p);
        pd.call();
        System.out.println("------------");

        // 需要:我想在接电话后,听音乐
        pd = new MusicPhoneDecorate(p);
        pd.call();
        System.out.println("------------");

        // 需要:我要想手机在接前听彩铃,接后听音乐
        // 本人提供装璜类,在打电话前听彩铃,打电话后听音乐
        pd = new RingPhoneDecorate(new MusicPhoneDecorate(p));
        pd.call();
        System.out.println("----------");
        // 想想咱们在 IO 流中的应用
        // InputStream is = System.in;
        // InputStreamReader isr = new InputStreamReader(is);
        // BufferedReader br = new BufferedReader(isr);
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter((new OutputStreamWriter(System.out)));

        Scanner sc = new Scanner(System.in);
    }
}
正文完
 0