反射

反射 Reflection

反射机制允许程序在执行期间借助于Reflection API,取得任何类的内部信息,并且能直接操作任意对象的内部属性和方法。

加载完类之后,在堆内存中就会产生一个Class类型的对象(一个类只有一个),这个对象就包含了完整的类信息。我们可以通过这个对象看清类的结构,我们称之为反射。

反射

静态语言:C C++ Java

动态语言:在运行时可以改变内部结构JavaScript PHP C# Erlang等等

其实java应该是准动态语言,因为它可以通过反射机制,实现一些类似于动态语言的一些操作。

如何看待反射和封装性?

​ 首先这两个技术并不矛盾,首先封装性是我们的权限修饰符,它更多的是一种提示作用,也可以这样想就是说java希望我们不要在类的外部使用私有方法等等,但是反射可以这样做。总而言之就是可以但不建议。

什么时候使用反射?什么时候使用new 构造器?

​ 有时候我们在编译的时候,无法确定创建哪个类的对象,此时就要使用反射;相对应的,如果在编译之前我们就已经知道使用哪个类的对象了,就可以直接通过构造器 new对象。

​ 比如我们在在网站的时候,启动了项目,我们此时不知道用户会执行那个操作,他有可能会登录,有可能会注册,此时就可以使用反射了。

Class类

​ 程序通过javac.exe命令行以后,会生成一个或者多个字节码文件(.class结尾)

​ 接着我们使用java.exe命令对某个字节码文件进行解释运行,相当于将某个字节码文件加载到内存中,这个就称为运行时类。这个运行时类就是Class的一个对象。我们也可以这样理解类其实也是对象(Class这个类的对象)。所以说java中万事万物皆对象!

类的加载:

反射

反射

哪些类型可以有Class对象:

反射

类的加载器:

反射

反射

通过getParent()方法获取上一层的类加载器对象。

获取Class实例的获取
import org.junit.Test;

public class ClassTest {

    @Test
    public void test01() {
        //方式1  调用运行时类的属性
        Class class1=BigPerson.class;
        System.out.println(class1);
        //方式2  通过运行时类的对象的方法
        BigPerson person=new BigPerson();
        Class class2=person.getClass();
        System.out.println(class2.getName());
        //方式3  Class的静态方法
        try {
            Class class3=Class.forName("BigPerson");//全限定名称
            System.out.println(class3);
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }
        //方式4  通过类的加载器
        try {
            ClassLoader classLoader=ClassTest.class.getClassLoader();
            Class class4=classLoader.loadClass("BigPerson");
            System.out.println(class4);
        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }



    }
}
class BigPerson{
    private String name;
    private int age;
    public String description;

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

    public BigPerson() {
    }

    private BigPerson(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 String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
    private String show(String id){
        System.out.println("你的id是:"+id);
        return id;
    }
    private void show(){
        System.out.println("你的id是:"+"123");
    }
}
读取配置文件的方式:
@Test
public void test02() throws Exception {
    Properties properties1=new Properties();
    InputStream inputStream=new FileInputStream("lala.properties");
    properties1.load(inputStream);
    String name1 = properties1.getProperty("name");
    String password1 = properties1.getProperty("password");
    String age1=properties1.getProperty("age");

    Properties properties2=new Properties();
    ClassLoader classLoader=ClassTest.class.getClassLoader();
    InputStream resourceAsStream = classLoader.getResourceAsStream("lala1.properties");
    properties2.load(resourceAsStream);
    String name2 = properties2.getProperty("name");
    String password2 = properties2.getProperty("password");
    String age2=properties2.getProperty("age");


    System.out.println(name1+" "+password1+" "+age1);
    System.out.println(name2+" "+password2+" "+age2);

}
通过反射构造类的实例
import org.junit.Test;

import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Properties;

public class ClassTest {
    @Test
    public void test03() throws
            IllegalAccessException,
            InstantiationException,
            ClassNotFoundException,
            NoSuchMethodException,
            InvocationTargetException {
        //使用了泛型(空参构造器)
        Class<BigPerson> clazz1=BigPerson.class;
        BigPerson bigPerson1=clazz1.newInstance();
        System.out.println(bigPerson1);
        //不使用泛型(空参构造器)
        Class clazz2=bigPerson1.getClass();
        BigPerson bigPerson2=(BigPerson)clazz2.newInstance();
        System.out.println(bigPerson2);
        //调用构造器
        Class clazz3=Class.forName("BigPerson");
        Constructor<BigPerson> constructor1=clazz3.getDeclaredConstructor(String.class,Integer.class,String.class);
        BigPerson bigPerson3=constructor1.newInstance("geng",new Integer(22),"peng");
        System.out.println(bigPerson3.toString());
        //调用私有构造器
        ClassLoader classLoader1=ClassTest.class.getClassLoader();
        Class clazz4=classLoader1.loadClass("BigPerson");
        Constructor<BigPerson> constructor2=clazz4.getDeclaredConstructor(Integer.class,String.class);
        constructor2.setAccessible(true);//如果是私有构造器必须使用这个
        BigPerson bigPerson4 = constructor2.newInstance(new Integer(13), "lala");
        System.out.println(bigPerson4);
    }
}
class BigPerson{
    private String name;
    private Integer age;
    public String description;

    public BigPerson(String name, Integer age, String description) {
        this.name = name;
        this.age = age;
        this.description = description;
    }
    private BigPerson( Integer age, String description) {
        this.age = age;
        this.description = description;
    }

    public BigPerson() {
        System.out.println("调用了空参构造器");
    }

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

    private BigPerson(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 String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
    private String show(String id){
        System.out.println("你的id是:"+id);
        return id;
    }
    private void show(){
        System.out.println("你的id是:"+"123");
    }
}
体会一下反射的动态性:
@Test
public void test04() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
    int n= new Random().nextInt(4);
    System.out.println(n);
    String classPath=getClassPath(n);
    Class clazz=Class.forName(classPath);

    //Object obj=clazz.newInstance();
    Constructor constructor=clazz.getDeclaredConstructor();
    constructor.setAccessible(true);
    Object obj=constructor.newInstance();
    System.out.println(obj);
}

private String getClassPath(int n) {
    switch (n){
        case 1:return "BigPerson";
        case 2:return "java.util.Date";
        case 3:return "java.lang.String";
        case 0:return "java.lang.Object";
    }
    return "";
}
通过反射获取类的属性信息
import org.junit.Test;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;


public class ClassTest {
    @Test
    public void test01(){
        Class clazz=BigPerson.class;
        //获取父类和子类中的public属性
        Field[] fields1=clazz.getFields();
        for(Field field:fields1){
            System.out.println(field);
        }
        System.out.println();
        //获取子类所有声明的属性值
        Field[] fields2=clazz.getDeclaredFields();
        for(Field field:fields2){
            System.out.println(Modifier.toString(field.getModifiers()));//获取权限修饰符
            System.out.println(field.getName());//获取属性名
            System.out.println(field.getType());//获取数据类型
        }
    }

}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.TYPE,ElementType.CONSTRUCTOR})
@interface MyAnnotation{
    String value() default "geng";
}
class Big{
    private int a;
    public String b;

    public Big(int a, String b) {
        this.a = a;
        this.b = b;
    }

    public Big() {
    }
}
@MyAnnotation("hello")
class BigPerson extends Big{
    @MyAnnotation("lala")
    private String name;
    private Integer age;
    public String description;


    public BigPerson(String name, Integer age, String description) {
        this.name = name;
        this.age = age;
        this.description = description;
    }
    private BigPerson( Integer age, String description) {
        this.age = age;
        this.description = description;
    }

    public BigPerson() {
        System.out.println("调用了空参构造器");
    }

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

    private BigPerson(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 String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
    @MyAnnotation
    private String show(String id){
        System.out.println("你的id是:"+id);
        return id;
    }
    private void show(){
        System.out.println("你的id是:"+"123");
    }
}
通过属性获取方法信息:
import org.junit.Test;


import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;


public class ClassTest {
    @Test
    public void test01(){

        Class clazz=BigPerson.class;
        //获取当前类所有声明的方法
        Method[] methods=clazz.getDeclaredMethods();
        //获取当前类及其父类(直接父类和间接父类)的所有public方法
        Method[] methods1=clazz.getMethods();
        //获取当前类某个方法上面的注解
        for(Method method:methods){
            Annotation[] annotations=method.getAnnotations();
            for(Annotation annotation:annotations){
                System.out.println(annotation);
            }
        }
        System.out.println();
        //获取方法的权限修饰符
        for(Method method:methods){
            System.out.println(Modifier.toString(method.getModifiers()));
        }
        //获取方法的返回值类型
        for(Method method:methods){
            System.out.println(method.getReturnType());
        }
        //获取方法的方法名
        for(Method method:methods){
            System.out.println(method.getName());
        }
        //获取方法的形参列表
        for(Method method:methods){
            System.out.print(method.getName()+"   :");
            Parameter[] parameters=method.getParameters();
            if(parameters!=null&&parameters.length!=0){
                for(Parameter parameter:parameters){
                    //System.out.print(parameter.getName());
                    System.out.println(parameter.getType());
                    //......
                }
            }
            System.out.println();
        }



        //抛出的异常

    }

}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.TYPE,ElementType.CONSTRUCTOR})
@interface MyAnnotation{
    String value() default "geng";
}
class Big{
    private int a;
    public String b;

    public Big(int a, String b) {
        this.a = a;
        this.b = b;
    }

    public Big() {
    }
}
@MyAnnotation("hello")
class BigPerson extends Big{
    @MyAnnotation("lala")
    private String name;
    private Integer age;
    public String description;


    public BigPerson(String name, Integer age, String description) {
        this.name = name;
        this.age = age;
        this.description = description;
    }
    private BigPerson( Integer age, String description) {
        this.age = age;
        this.description = description;
    }

    public BigPerson() {
        System.out.println("调用了空参构造器");
    }

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

    private BigPerson(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 String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
    @MyAnnotation
    private String show(String id){
        System.out.println("你的id是:"+id);
        return id;
    }
    private void show(){
        System.out.println("你的id是:"+"123");
    }
}
import org.junit.Test;


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


public class ClassTest {
    @Test
    public void test01() {
        //获取父类的Class对象
        Class clazz=BigPerson.class.getSuperclass();
        System.out.println(clazz);
        //获取带泛型的父类
        Type type=BigPerson.class.getGenericSuperclass();
        System.out.println(type);
        //获取泛型参数
        ParameterizedType parameterizedTypes=(ParameterizedType)type;
        Type[] types=parameterizedTypes.getActualTypeArguments();
        for(Type type1:types){
            System.out.println(type1.getTypeName());
        }

        //获取运行时类实现的接口,所在包,注解等等信息
    }


}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.TYPE,ElementType.CONSTRUCTOR})
@interface MyAnnotation{
    String value() default "geng";
}
class Big<T>{
    private int a;
    public String b;

    public Big(int a, String b) {
        this.a = a;
        this.b = b;
    }

    public Big() {
    }
}
@MyAnnotation("hello")
class BigPerson extends Big<String>{
    @MyAnnotation("lala")
    private String name;
    private Integer age;
    public String description;


    public BigPerson(String name, Integer age, String description) {
        this.name = name;
        this.age = age;
        this.description = description;
    }
    private BigPerson( Integer age, String description) {
        this.age = age;
        this.description = description;
    }

    public BigPerson() {
        System.out.println("调用了空参构造器");
    }

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

    private BigPerson(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 String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
    @MyAnnotation
    private String show(String id){
        System.out.println("你的id是:"+id);
        return id;
    }
    private void show(){
        System.out.println("你的id是:"+"123");
    }
}
通过反射操作属性
import org.junit.Test;


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


public class ClassTest {
    @Test
    public void test01() throws NoSuchFieldException, IllegalAccessException, InstantiationException {
        Class<BigPerson> clazz=BigPerson.class;
        Field fieldName=clazz.getDeclaredField("name");
        BigPerson bigPerson=clazz.newInstance();
        fieldName.setAccessible(true);
        fieldName.set(bigPerson,"lala");

        System.out.println(bigPerson.getName());
    }


}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.TYPE,ElementType.CONSTRUCTOR})
@interface MyAnnotation{
    String value() default "geng";
}
class Big<T>{
    private int a;
    public String b;

    public Big(int a, String b) {
        this.a = a;
        this.b = b;
    }

    public Big() {
    }
}
@MyAnnotation("hello")
class BigPerson extends Big<String>{
    @MyAnnotation("lala")
    private String name;
    private Integer age;
    public String description;


    public BigPerson(String name, Integer age, String description) {
        this.name = name;
        this.age = age;
        this.description = description;
    }
    private BigPerson( Integer age, String description) {
        this.age = age;
        this.description = description;
    }

    public BigPerson() {
        System.out.println("调用了空参构造器");
    }

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

    private BigPerson(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 String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
    @MyAnnotation
    private String show(String id){
        System.out.println("你的id是:"+id);
        return id;
    }
    private void show(){
        System.out.println("你的id是:"+"123");
    }
}
通过反射操作方法
import org.junit.Test;


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


public class ClassTest {
    @Test
    public void test01() throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Class<BigPerson> clazz=BigPerson.class;
        BigPerson bigPerson=clazz.newInstance();
        Method methodShow1=clazz.getDeclaredMethod("show",String.class);
        Method methodShow2=clazz.getDeclaredMethod("show");

        methodShow1.setAccessible(true);
        String result1=(String)methodShow1.invoke(bigPerson,"我是一个形参");
        System.out.println(result1);

        methodShow2.setAccessible(true);
        String result2=(String)methodShow2.invoke(bigPerson);
        System.out.println(result2);

        //调用静态方法
        Method methodShow3=clazz.getDeclaredMethod("lala",String.class);
        methodShow3.setAccessible(true);
        String result3=(String)methodShow3.invoke(BigPerson.class,"geng");
        System.out.println(result3);
    }


}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.TYPE,ElementType.CONSTRUCTOR})
@interface MyAnnotation{
    String value() default "geng";
}
class Big<T>{
    private int a;
    public String b;

    public Big(int a, String b) {
        this.a = a;
        this.b = b;
    }

    public Big() {
    }
}
@MyAnnotation("hello")
class BigPerson extends Big<String>{
    @MyAnnotation("lala")
    private String name;
    private Integer age;
    public String description;


    public BigPerson(String name, Integer age, String description) {
        this.name = name;
        this.age = age;
        this.description = description;
    }
    private BigPerson( Integer age, String description) {
        this.age = age;
        this.description = description;
    }

    public BigPerson() {
        System.out.println("调用了空参构造器");
    }

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

    private BigPerson(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 String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
    @MyAnnotation
    private String show(String id){
        System.out.println("你的id是:"+id);
        return id;
    }
    private void show(){
        System.out.println("你的id是:"+"123");
    }
    private static String lala(String s){
        return "lala"+s;
    }
}
上一篇:NetSuite 货品销售描述语言异常


下一篇:cocos2dx解决中文乱码方法