Java面向对象(六)

Java面向对象(六)

1.1反射

java的灵魂。
概念:在运行状态下,对于任何一个类,都能够知道类的属性和方法,对于任何一个对象,都能够调用它的任意一个方法和属性。这种动态获取信息的行为叫做反射。(反射和封装的思想是相违背的)

public class Person {
    public String name;
    protected int age;
    char gender;
    private String email;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                ", email='" + email + '\'' +
                '}';
    }

    public void speak(String s){
        System.out.println(s);
    }

    protected void speak(){
        System.out.println("protected speak()");
    }

    void run(){
        System.out.println("running");
    }

    private String eat(String s){
        System.out.println("private method()");
        return "eating " + s;
    }

    public void test1(){
        System.out.println("test1");
    }
    public void test2(String s,int i){
        System.out.println(s + i);
    }
}

public class Student {

    public Student(){
        System.out.println("我是无参构造器...");
    }

    public Student(char name){
        System.out.println("姓名 " + name);
    }

    public Student(String name){
        System.out.println("姓名 " + name);
    }

    public Student(String name,int age){
        System.out.println("姓名 " + name +" " + "年龄 " + age);
    }

    protected Student(boolean b){
        System.out.println("protected " + b);
    }

    private Student(int age){
        System.out.println(age);
    }
}
import java.io.Serializable;
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.List;

public class ReflectDemo implements Serializable,Cloneable{
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException {
        //getPackage();
        //getClassObject();
        //getSuperClassAndInterfaceImpl();
        //getConstructors();
        //getAttributes();
        //getMethods();
        //getAnyMethod();
        //genericCheck();
        modifyArray();
    }

    /**
     * 1.获取当前类的包名
     */
    public static void getPackage(){
        ReflectDemo reflectDemo = new ReflectDemo();
        System.out.println(reflectDemo.getClass().getName());
    }

    /**
     * 2. 获取Class的类对象
     */
    public static void getClassObject(){
        Class<?> c1 = null;
        Class<?> c2 = null;
        Class<?> c3 = null;
        /**
         * 第一种最常用
         * 通过Class的静态方法forName()获取
         */
        try {
            c1 = Class.forName("com.oop.reflection.ReflectDemo");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        /**
         * 因为所有的类都继承自Object
         * 所以Object的getClass()可以获取
         */
        c2 = new ReflectDemo().getClass();

        /**
         * 任何数据类型(包括基本数据类型)都有一个静态的class属性
         */
        c3 = ReflectDemo.class;

        System.out.println(c1.getName());
        System.out.println(c2.getName());
        System.out.println(c3.getName());
    }

    /**
     * 3.获取父类和接口的实现
     */
    public static void getSuperClassAndInterfaceImpl() throws ClassNotFoundException {
        Class<?> clazz = Class.forName("com.oop.reflection.ReflectDemo");
        //取父类
        Class<?> superClazz = clazz.getSuperclass();
        System.out.println(superClazz.getName());
        Class<?> [] interfaces = clazz.getInterfaces();
        for (int i = 0; i < interfaces.length ; i++) {
            System.out.println((i+1) + " " + interfaces[i].getName());
        }
    }

    /**
     * 4.获取类的构造方法
     */
    public static void getConstructors() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //加载类对象
        Class clazz = Class.forName("com.oop.reflection.Student");

        System.out.println("-----------构造方法列表-------------");
        //这种方式只能获取到公有的构造器
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor c : constructors){
            System.out.println(c);
        }

        Constructor constructor = clazz.getConstructor(null);
        System.out.println(constructor);
        //Student student = new Student();
        //反射调用构造器

            Object obj = constructor.newInstance();
            System.out.println(obj);


        //调用私有构造器
        constructor = clazz.getDeclaredConstructor(int.class);
        System.out.println(constructor);


            constructor.setAccessible(true);
            obj = constructor.newInstance(20);
            System.out.println(obj);

            System.out.println("------------------------------");
            //获取所有构造器
            constructors = clazz.getDeclaredConstructors();
            for (Constructor c : constructors){
                System.out.println(c);
            }
        }

    /**
     * 5.获取一个类中的所有属性
     */
    public static void getAttributes() throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class clazz = Class.forName("com.oop.reflection.Person");

        //获取类中的公有属性
        Field[] fields = clazz.getFields();
        for (Field field : fields){
            System.out.println(field);
        }

        System.out.println("------获取所有属性-------");
        fields = clazz.getDeclaredFields();
        for (Field field : fields){
            System.out.println(field);
        }

        System.out.println();
        //调用公有的属性
        Field f = clazz.getField("name");
        System.out.println(f);
        Object obj = clazz.getConstructor().newInstance();
        f.set(obj,"YCL");
        System.out.println(obj);

        System.out.println("-----------------");
        //私有属性
        f = clazz.getDeclaredField("email");
        System.out.println(f);
        f.setAccessible(true);
        f.set(obj,"ycl@a.com");
        System.out.println(obj);

        //TODO 把age,和gender属性赋值
    }

    /**
     * 6.获取类中所有的方法
     */
    public static void getMethods() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class clazz = Class.forName("com.oop.reflection.Person");

        //获取公有方法,包括父类
        Method[] methods = clazz.getMethods();
        for (Method m : methods){
            System.out.println(m);
        }

        System.out.println();

        //获取私有方法
        methods = clazz.getDeclaredMethods();
        for (Method m : methods){
            System.out.println(m);
        }

        System.out.println();
        //调用公有方法
        Method m = clazz.getMethod("speak",String.class);
        Object obj = clazz.getConstructor().newInstance();
        m.invoke(obj,"Hello");

        //调用私有方法
        m = clazz.getDeclaredMethod("eat", String.class);
        m.setAccessible(true);
        Object res = m.invoke(obj,"Apple");
        System.out.println(res);
    }

    /**
     * 7.调用某个类的方法
     */

    public static void getAnyMethod() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Class clazz = Class.forName("com.oop.reflection.Person");
        Method method = clazz.getMethod("test1");
        method.invoke(clazz.newInstance());

        method = clazz.getMethod("test2", String.class, int.class);
        method.invoke(clazz.newInstance(),"a",12);
    }

    /**
     * 8.通过反射绕过检查泛型
     */
    public static void genericCheck() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        //存一个非Integer的对象
        Method method = list.getClass().getMethod("add", Object.class);
        method.invoke(list,"反射检查泛型");

        for (Object obj : list){
            System.out.println(obj);
        }

        System.out.println(list.get(2));
    }

    /**
     * 9,通过反射修改数组信息
     */

    public static void modifyArray(){
        int[] a = {1,2,3,4,5,6,7};
        System.out.println(a.length);
        int[] newA = (int[]) modifySize(a,10);
        printArray(newA);

        String[] strs = {"a","b","c"};
        String[] newStrs = (String[]) modifySize(strs,5);
        printArray(newStrs);
    }

    private static void printArray(Object obj) {
        Class<?> c = obj.getClass();
        if (!c.isArray()){
            return;
        }
        Class<?> array = obj.getClass().getComponentType();
        System.out.println("Array type:"+array.getName());
        System.out.println("Array length:"+ Array.getLength(obj));
        for (int i = 0; i < Array.getLength(obj) ; i++) {
            System.out.print(Array.get(obj,i) + " ");
        }
        System.out.println();
    }

    private static Object modifySize(Object obj, int length) {
        Class<?> array = obj.getClass().getComponentType();
        Object newArray = Array.newInstance(array,length);
        int l = Array.getLength(obj);

        System.arraycopy(obj,0,newArray,0,l);
        return newArray;
    }

}

1.2反射和代理

public interface Subject {
    String eating(String name,int num);
}
import com.oop.reflection.proxy.Subject;

public class RealSubject implements Subject {
    @Override
    public String eating(String name, int num) {
        return "Eating with " + name + " and NO. is " + num;
    }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MyProxy implements InvocationHandler {
    private Object obj = null;

    public Object bind(Object obj){
        this.obj = obj;
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                obj.getClass().getInterfaces(),this);
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object action = method.invoke(this.obj,args);
        return action;
    }
}
import com.oop.reflection.proxy.impl.RealSubject;

public class TestProxy {
    public static void main(String[] args) {
        //代理
        MyProxy proxy = new MyProxy();
        //绑定代理对象
        Subject subject = (Subject) proxy.bind(new RealSubject());
        String res = subject.eating("Tom",1999);
        System.out.println(res);
    }
}

1.3反射和工厂

public class Factory {
    public static Fruit getInstance(String className){
        Fruit fruit = null;

        try {
            //通过反射构建工厂对象
            fruit =(Fruit)Class.forName(className).newInstance();
        } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }

        return fruit;
    }
}
public interface Fruit {
    void eat();
}
import com.oop.reflection.factory.Fruit;

public class Apple implements Fruit {
    @Override
    public void eat() {
        System.out.println("Eating apple");
    }
}
import com.oop.reflection.factory.Fruit;

public class Orange implements Fruit {
    @Override
    public void eat() {
        System.out.println("Eating orange");
    }
}
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class FactoryTest {
    public static void main(String[] args) throws IOException {
        String key="className";
        Fruit fruit = Factory.getInstance(getValue(key));
        if (fruit != null){
            fruit.eat();
        }
    }
    public static String getValue(String key) throws IOException {
        //配置文件对象
        Properties prop = new Properties();
        //通过反射读取类路径下的文件
        InputStream in =FactoryTest.class.getResourceAsStream("prop.txt");

        prop.load(in);

        return prop.getProperty(key);
    }
}
/**prop.txt*/
className=com.oop.reflection.factory.impl.Orange

1.4 ClassLoader

/**
 * 什么是ClassLoader
 * 把类加载到JVM,bootstrap启动加载器,userDefineClassLoader用户自定义类加载器
 * System ClassLoader ---> Extension ClassLoader ---> Bootstrap ClassLoader自底向下检查类是否加载
 * 自顶向下尝试加载类
 * System ClassLoader <--- Extension ClassLoader <--- Bootstrap ClassLoader
 * Bootstrap ClassLoader
 * JVM核心库的类装载,该类加载器无法直接获取
 * Extension ClassLoader
 * 负责jdk_home/lib/ext/目录下的jar或者-D java.ext.dirs指定目录下的jar包装载
 * System ClassLoader
 * 负责java -classpath或者-D java.class.path所指定目录下的jar包的装载
 */
public class ClassLoaderTest {
    public static void main(String[] args) throws ClassNotFoundException {
        getClassLoader();
    }

    public static void getClassLoader() throws ClassNotFoundException {
        //获取系统类加载器
        ClassLoader classLoader = ClassLoader.getSystemClassLoader();
        System.out.println("System ClassLoader:" + classLoader);

        //获取系统类加载器的父类
        classLoader = classLoader.getParent();
        System.out.println("Extension ClassLoader:" + classLoader);

        //获取不到
        classLoader = classLoader.getParent();
        System.out.println("Bootstrap ClassLoader:" + classLoader);

        //获取当前类的ClassLoader
        classLoader = Class.forName("com.oop.reflection.classloader.ClassLoaderTest").getClassLoader();
        System.out.println("ClassLoaderTest:" + classLoader);

        //获取Object的ClassLoader
        classLoader = Class.forName("java.lang.Object").getClassLoader();
        System.out.println("Object:" +  classLoader);

    }
}

posted @ 2020-07-15 21:55  Dave-Mo  阅读(67)  评论(0)    收藏  举报