java 反射

1.反射概述

package com.yl.pdfdemo.day08.p6;

import org.junit.Test;

import java.lang.annotation.ElementType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @Author wfj
 * @Date 2021/7/2
 * @Description 反射
 * @Version 1.0
 */

public class ReflectionTest {
    /**
     * 反射:被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,
     *  并且能操作任意对象的内部属性和方法
     *
     *  关于java.lang.Class类的理解
     *
     *  1.类的加载过程
     *      程序经过javac.exe命令以后,会生成一个或者多个字节码文件(.class结尾)
     *      接着我们使用java.exe命令对某个字节码文件解析运行,相当于将某个字节码文件加载到内存中。
     *      此过程称为类的加载,加载到内存中的类,我们称之为运行时类,此运行时类就作为Class的一个实例
     *
     *  2.换句话说,Class的实例就对应着一个运行时类
     */

    //反射之前对于Animal的创建
    @Test
    public void test1() {
        Animal animal = new Animal("xiaobai",13);
        animal.show();

        //在Animal类外部,不可以调用其内部的私有的属性,构造器,方法
        //Animal animal1 = new Animal("小白");
    }

    //有了反射后,对Aniaml的操作
    @Test
    public void test2() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        //获取类对象
        Class clazz = Animal.class;
        //1.通过反射构造对象
        //方式一
        Constructor constructor = clazz.getConstructor(String.class, int.class);
        Object object = constructor.newInstance("小黑",12);
        Animal animal = (Animal) object;
        System.out.println(animal.toString());//Animal{name='小黑', age=12}

        //方式二
        //newInstance(),调用了运行时类的空参构造器,所以类一般都要提供空参构造器,并且是public的
        Animal a1 = (Animal)clazz.newInstance();
        System.out.println(a1); //Animal{name='null', age=0}

        //2.通过反射,调用指定的属性或方法
        Field age = clazz.getDeclaredField("age");
        age.set(animal,11);
        System.out.println(animal.toString()); //Animal{name='小黑', age=11}

        //调用方法
        Method show = clazz.getDeclaredMethod("show");
        show.invoke(animal);
        Method show1 = clazz.getDeclaredMethod("showType",String.class);
        show1.invoke(animal,"治愈系");

        //注意:通过反射可以获取Animal类的私有结构:属性,方法,构造器
        //调用私有构造器
        Constructor constructor1 = clazz.getDeclaredConstructor(String.class);
        constructor1.setAccessible(true);
        Animal animal1 = (Animal) constructor1.newInstance("小紫");
        System.out.println(animal1.toString()); // Animal{name='小紫', age=0}
        //调用私有属性
        Field name = clazz.getDeclaredField("name");
        name.setAccessible(true);
        name.set(animal1,"大桥");
        System.out.println(animal1.toString());// Animal{name='大桥', age=0}
        //调用私有方法
        Method method = clazz.getDeclaredMethod("showAgeAndName", int.class, String.class);
        method.setAccessible(true);
        String str = (String)method.invoke(animal1,18,"xiu");
        System.out.println(str); // age=18and name = xiu
    }

    //获取Class实例的方式
    @Test
    public void test3() throws ClassNotFoundException {
        //方式一:调用运行时类的属性.class
        Class clazz1 = Animal.class;
        System.out.println(clazz1);//class com.yl.pdfdemo.day08.p6.Animal

        //方式二:通过运行时类的对象
        Animal animal = new Animal();
        Class clazz2 = animal.getClass();
        System.out.println(clazz2);//class com.yl.pdfdemo.day08.p6.Animal

        //方式三:调用Class的静态方法,forName(String classPath)
        Class clazz3 = Class.forName("com.yl.pdfdemo.day08.p6.Animal");
        System.out.println(clazz3);//class com.yl.pdfdemo.day08.p6.Animal
        System.out.println(clazz1 == clazz2); //true
        System.out.println(clazz1 == clazz3); //true

        //方式四:使用类的加载器
        ClassLoader classLoader = ReflectionTest.class.getClassLoader();
        Class clazz4 = classLoader.loadClass("com.yl.pdfdemo.day08.p6.Animal");
        System.out.println(clazz4); //class com.yl.pdfdemo.day08.p6.Animal

    }

    //Class实例可以是哪些结构?接口,基本数据类型,普通类,注解,枚举,数组,接口,void等
    @Test
    public void test4() {
        Class clazz1 = Object.class;
        Class clazz2 = Comparable.class;
        Class clazz3 = int.class;
        Class clazz4 = String[].class;
        Class clazz5 = ElementType.class;
        Class clazz6 = Override.class;
        Class clazz7 = int[][].class;
        Class clazz8 = void.class;
        Class clazz9 = Class.class;

        //只要数组的元素类型和维度一样,就是同一个Class
        int[] a = new int[10];
        int[] b = new int[100];
        Class clazz10 = a.getClass();
        Class clazz11 = b.getClass();
        System.out.println(clazz10 == clazz11); //true
    }


}

package com.yl.pdfdemo.day08.p6;

/**
 * @Author wfj
 * @Date 2021/7/2
 * @Description
 * @Version 1.0
 */

public class Animal {
    private String name;
    public int age;

    public Animal() {
    }

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

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

    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;
    }

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

    public String showType(String type) {
        System.out.println(type);
        return type;
    }

    private String showAgeAndName(int age,String name) {
        System.out.println("age="+age+"and name = "+name);
        return "age=" + age + "and name = "+ name;
    }

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

2.用到的测试的文件
1)Creature类

package com.yl.pdfdemo.day08.p6;

import java.io.Serializable;

/**
 * @Author wfj
 * @Date 2021/7/2
 * @Description
 * @Version 1.0
 */

public class Creature<T> implements Serializable {
    private char gender;
    public double weight;

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

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

}

2)Person类

package com.yl.pdfdemo.day08.p6;

import java.io.IOException;

/**
 * @Author wfj
 * @Date 2021/7/2
 * @Description
 * @Version 1.0
 */

@MyAnnotation(value = "p")
public class Person extends Creature<String> implements Comparable<String>,MyInterface {

    private String name;
    int age;
    public int id;
    private static String gender;

    public Person() {

    }

    @MyAnnotation(value = "abc")
    private Person(String name) {
        this.name = name;
    }

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

    @MyAnnotation
    private String show(String national) {
        System.out.println("国籍为:"+national);
        return national;
    }

    public String display(String str) throws IOException,NullPointerException {
        return str;
    }

    @Override
    public void info() {
        System.out.println("Person info...");
    }

    @Override
    public int compareTo(String o) {
        return 0;
    }

    private static void print() {
        System.out.println("static method");
    }

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

3)MyAnnotation

package com.yl.pdfdemo.day08.p6;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;

/**
 * @Author wfj
 * @Date 2021/7/2
 * @Description
 * @Version 1.0
 */

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String value() default "hello vue";
}

4)MyInterface

package com.yl.pdfdemo.day08.p6;

/**
 * @Author wfj
 * @Date 2021/7/2
 * @Description
 * @Version 1.0
 */

public interface MyInterface {
    void info();
}

3.获取运行时类的结构

package com.yl.pdfdemo.day08.p6;

import org.junit.Test;

import java.lang.annotation.Annotation;
import java.lang.reflect.*;

/**
 * @Author wfj
 * @Date 2021/7/2
 * @Description 通过反射获取运行时类的结构
 * @Version 1.0
 */

public class test {

    //获取当前运行时类的属性
    @Test
    public void test1() {
        Class clazz1 = Person.class;

        //getFields():获取当前运行时类及其父类中声明为public的属性
        Field[] fields1 = clazz1.getFields();
        for (Field field : fields1) {
            System.out.println(field);
        }
        System.out.println("============");

        //getDeclaredFields():获取当前运行时类的所有属性,不包含父类中声明的属性
        Field[] fields2 = clazz1.getDeclaredFields();
        for (Field field : fields2) {
            System.out.println(field);
        }

        //除此之外,还可以获取权限修饰符,数据类型,变量名
        Field[] fields3 = clazz1.getDeclaredFields();
        for (Field field : fields3) {
            //权限修饰符
            int modeifier = field.getModifiers();
            System.out.print(Modifier.toString(modeifier) + "\t");

            //数据类型
            Class type = field.getType();
            System.out.print(type.getName() + "\t");

            //变量名
            String name = field.getName();
            System.out.print(name);
            System.out.println();
        }
        //以上输出结果
        /**
         * private	java.lang.String	name
         * 	int	age
         * public	int	id
         */
    }

    //获取运行时类的方法的结构
    @Test
    public void test2() {
        Class clazz = Person.class;

        //getMethods() 获取当前运行时类及其所有父类中声明为public的方法
        Method[] methods1 = clazz.getMethods();
        for (Method method : methods1) {
            System.out.println(method);
        }

        //getMethods() 获取当前运行时类的所有父方法,不包含父类的方法
        Method[] methods2= clazz.getDeclaredMethods();
        for (Method method : methods2) {
            System.out.println(method);
        }

        System.out.println("=================");

        //获取方法的权限修饰符,返回值类型,注解,方法名等等
        Method[] methods3= clazz.getDeclaredMethods();
        for (Method method : methods3) {
            //获取方法上的注解
            Annotation[] annotations = method.getAnnotations();
            for (Annotation annotation : annotations) {
                System.out.println(annotation);
            }

            //获取权限修饰符
            System.out.print(Modifier.toString(method.getModifiers()) + "\t");

            //获取方法返回值类型
            System.out.print(method.getReturnType().getName() + "\t");

            //获取方法名
            System.out.print(method.getName() + "\t");
            System.out.print("(");

            //获取形参列表
            Class[] parameterTypes = method.getParameterTypes();
            if(!(parameterTypes == null && parameterTypes.length == 0)) {
                for (int i = 0; i < parameterTypes.length; i++) {
                    if (i == parameterTypes.length-1) {
                        System.out.print(parameterTypes[i].getName());
                        break;
                    }
                    System.out.print(parameterTypes[i].getName() + ",");
                }
            }
            System.out.print(")");

            //获取抛出的异常
            Class[] exceptionTypes = method.getExceptionTypes();
            if (!(exceptionTypes == null && exceptionTypes.length == 0)) {
                System.out.print("throw");
                for (int i = 0; i < exceptionTypes.length; i++) {
                    if (i == exceptionTypes.length - 1) {
                        System.out.print(exceptionTypes[i].getName());
                        break;
                    }
                    System.out.println(exceptionTypes[i].getName() + ",");
                }
            }


            System.out.println();
            //结果
            /**
             * public	int	compareTo	(java.lang.String)throw
             * public volatile	int	compareTo	(java.lang.Object)throw
             * public	void	info	()throw
             * @com.yl.pdfdemo.day08.p6.MyAnnotation(value=hello vue)
             * private	java.lang.String	show	(java.lang.String)throw
             * public	java.lang.String	display	(java.lang.String)throwjava.io.IOException,
             */
        }
    }


    //获取构造器结构
    @Test
    public void test3 () {
        Class clazz = Person.class;

        //getConstructors(): 获取当前运行时类声明为public的构造器
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor c : constructors) {
            System.out.println(c);
        }

        //getDeclaredConstructors(): 获取当前运行时类所有的构造器
        Constructor[] constructors1 = clazz.getDeclaredConstructors();
        for (Constructor c : constructors1) {
            System.out.println(c);
        }
    }

    //获取运行时类的父类
    @Test
    public void test4() {
        Class clazz = Person.class;
        Class superclass = clazz.getSuperclass();
        System.out.println(superclass);//class com.yl.pdfdemo.day08.p6.Creature
    }

    //获取运行时类帶泛型的父类
    @Test
    public void test5() {
        Class clazz = Person.class;
        Type genericSuperclass = clazz.getGenericSuperclass();
        System.out.println(genericSuperclass);//com.yl.pdfdemo.day08.p6.Creature<java.lang.String>

        //获取泛型类型
        ParameterizedType paramType = (ParameterizedType)genericSuperclass;
        Type[] arguments = paramType.getActualTypeArguments();
        System.out.println(((Class)arguments[0]).getName());//java.lang.String
    }


    //获取运行时类实现的接口
    @Test
    public void test6() {
        Class clazz = Person.class;
        Class[] interfaces = clazz.getInterfaces();
        for (Class c : interfaces) {
            System.out.println(c);
        }
        System.out.println();
        //获取运行时父类实现的接口
        Class[] interfaces1 = clazz.getSuperclass().getInterfaces();
        for (Class c : interfaces1) {
            System.out.println(c);
        }
    }

    //获取当前运行时类所在的包
    @Test
    public void test7() {
        Class clazz = Person.class;
        Package aPackage = clazz.getPackage();
        System.out.println(aPackage); //package com.yl.pdfdemo.day08.p6
    }

    //获取运行时类声明的注解
    @Test
    public void test8() {
        Class clazz = Person.class;
        Annotation[] annotations = clazz.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation); //@com.yl.pdfdemo.day08.p6.MyAnnotation(value=p)
        }
    }



}

4.调用运行时类的结构

package com.yl.pdfdemo.day08.p6;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @Author wfj
 * @Date 2021/7/13
 * @Description
 * @Version 1.0
 */

public class test1 {

    @Test
    public void test1() throws IllegalAccessException, InstantiationException, NoSuchFieldException {
        Class clazz = Person.class;
        //创建对象
        Person person = (Person) clazz.newInstance();
        //获取指定属性
        //要求声明的属性为public的,通常不用这种方式
        Field id = clazz.getField("id");
        //设置值
        id.set(person,1000);

        //获取某个对象当前属性的值
        int i = (int)id.get(person);
        System.out.println(i);
    }

    //操作运行时类的属性
    @Test
    public void test2() throws IllegalAccessException, InstantiationException, NoSuchFieldException {
        Class clazz = Person.class;
        Person person = (Person) clazz.newInstance();

        //获取指定属性
        Field name = clazz.getDeclaredField("name");
        //设置当前属性可以访问
        name.setAccessible(true);
        //设置值
        name.set(person,"yang");
        System.out.println(name.get(person)); // yang

        //获取静态属性,设置值,取值
        Field gender = clazz.getDeclaredField("gender");
        gender.setAccessible(true);
        gender.set(null,"男");
        System.out.println(gender.get(null)); //男
    }

    //操作运行时类的方法
    @Test
    public void test3() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class clazz = Person.class;
        Person person = (Person) clazz.newInstance();
        //获取指定的方法
        Method show = clazz.getDeclaredMethod("show", String.class);
        show.setAccessible(true);
        //调用方法
        String vue = (String)show.invoke(person, "vue");
        System.out.println(vue);
        System.out.println("=============");

        //调用静态方法
        Method print = clazz.getDeclaredMethod("print");
        print.setAccessible(true);
        //调用静态方法,第一个参数为Class对象
        Object o = print.invoke(Person.class);
        //或者
        //Object o = print.invoke(null);
        //如果方法没有返回值会返回null
        System.out.println(o);// null

    }

    //调用运行时类的构造器
    @Test
    public void test4() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class clazz = Person.class;
        //获取构造器
        Constructor constructor = clazz.getDeclaredConstructor(String.class);
        //保证此构造器是可以访问的
        constructor.setAccessible(true);
        //创建对象
        Person person = (Person)constructor.newInstance("tom");
        System.out.println(person); //Person{name='tom', age=0, id=0}

    }
}

5.类加载器额外概述

package com.yl.pdfdemo.day08.p6;

import org.junit.Test;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;

/**
 * @Author wfj
 * @Date 2021/7/2
 * @Description 类加载器
 * @Version 1.0
 */

public class ClassLoaderTest {

    @Test
    public void test1() {
        //对于自定义类,使用系统类加载器进行加载
        ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
        System.out.println(classLoader); // sun.misc.Launcher$AppClassLoader@18b4aac2
        //调用系统内加载器的getParent()方法:获取扩展类加载器
        ClassLoader classLoader1 = classLoader.getParent();
        System.out.println(classLoader1);  // sun.misc.Launcher$ExtClassLoader@439f5b3d
        //调用扩展类加载的getParent():无法获取引导类加载器
        //引导类加载器主要负责加载java核心类库,无法加载自定义类的
        ClassLoader classLoader2 = classLoader1.getParent();
        System.out.println(classLoader2); // null

        ClassLoader classLoader3 = String.class.getClassLoader();
        System.out.println(classLoader3); // null
    }

    /**
     * Properties:用来读取配置文件
     */
    @Test
    public void test2() throws Exception{
        Properties pros = new Properties();
        //方式一:默认加载路径是当前module下,如果配置文件在src下,需要指定路径
        FileInputStream is = new FileInputStream("src\\jdbc.properties");
        pros.load(is);
        System.out.println(pros.get("userName")); //root
        System.out.println(pros.get("password")); //123456

        //方式二:通过类的加载器,默认加载路径是src下
        ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
        InputStream is1 = classLoader.getResourceAsStream("jdbc.properties");
        pros.load(is1);
        System.out.println(pros.get("userName"));// root
        System.out.println(pros.get("password")); //123456
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值