java基础:反射。

  1. 反射机制
       反射机制:
      ①可以构造任意一个类的对象。
      ②可以获取任意一个对象所属类的信息。
      ③可以调用任意一个类的成员变量与方法。
      ④可以获取任意一个对象的属性与方法。

    反射可以理解为使用类的另一种方式:
       ①原本的方式:
       1)利用构造函数创建一个类的对象。
       2)获取这个对象的属性值、给对象的属性赋值。
       3)调用该类的方法操作该类。

       ①使用反射:
       1)获取类的字节码文件。
       2)调用Class类中相关的方法获取指定的成员对象(构造方法、成员变量、成员方法)。
       3)调用成员对象的相关方法使用对应的成员。

  2. Class类
       通过Class类获取类中的字节码文件对象。
       三种实例化Class对象的三种方式:
       1)通过完整类名获取。

     	Class.forName("完整类名")
    

       1)通过对象获取

     	对象.getClass()
    

       1)通过类名获取

     	类名.class()
    

    使用实例:
       可以发现三种方式得到结果是一样的,

    //获取A字节码文件对象,使用较多
Class  claZz1= Class.forName("N_Reflect.Ex01.A");
//调用GetClass获取
Class claZz2 = new A().getClass();
//通过静态属性.class获取
Class claZz3 = A.class ;
//同一个字节码文件
System.out.println(claZz1 == claZz2);
System.out.println(claZz2 == claZz3);
System.out.println("类名:"+ claZz1.getName());
System.out.println("类名:"+ claZz2.getName());
System.out.println("类名:"+ claZz3.getName());

   Class类常用方法:
    常用于将Class类对象实例化为自定义类对象,即可以通过一个给定的字符串(全类名)实例化一个本类的对象,可以通过无参、有参构造方法实例化对象。

public static Class<?> forName(String className) //实例化Class对象。
public Constructor[] getConstructors()//获取类中的所有方法。
public Field[] getDeclaredFields()//获取本类全部属性。
public Fileld[] getFileds()//获取继承而来的全部属性。
public Method[] getMethods()//获取类中的全部方法。
public Method getMethod(String name, Class...parmeterType)//获取Method对象并设置一个方法中的所有参数类型。
public Class[] getInterfaces()//获取类中的全部接口。
public String getName()//获取类的完整(包.类)名。
public Package getPackage()//得到一个类的包。
public Class getSuperclass()//得到一个类的父类。
public Object newInstance()//根据Class定义的类实例化对象。
public Class<?> getComponentType() 返回数组类型的Class。
public boolean isArray() //判断此Class是否是一个数组。

   Constructor类常用方法:
    Constructor类用于存储本类的构造方法。

public getModifiers()//获取构造方法的修饰符。
public String getName()//获取构造方法的名称。
publi Class<?>[] getParameterTypes()//获取构造方法中参数的类型。
public String toString()//返回构造方法的信息。
public T newInstance()//向构造方法中传递参数,实例化对象。 

   Method类常用方法:
      需要获取类中的全部方法,可以使用getMethod()方法,该方法返回一个Method类的对象数组,可以通过Method类进一步获取方法的具体信息。

public int getModifiers()//获取方法的修饰符
public String getName()//获取方法名称
public Class<?>[] getParamterTypes()//获取方法的全部参数类型。
public Class<?> getReturnType() //获取方法的返回值类型
public Class<?> getExceptionType()//获取方法的全部抛出异常
public Class<?>[] getExceptionType()//通过反射调用类中的方法

   Field类常用方法:
      使用Field类可以获取类的全部属性,有两个部分:父类继承的属性、本类的属性。
      1)public Field[] getFields()//获取实现的接口、父类的公共属性。
      2)public Field[] getDeclaredFields()//获取本类全部属性。

public int getModifiers()//获取本属性的修饰符
public String getName()//得到属性的名称
public boolean isAccessible()//判断属性是否可被外部调用
public void setAccessible(Boolean flag)//设置一个属性是否能被外部嗲用
public String toString()//返回Filed类的信息
public Object get(Object obj)//获取对象中的具体内容。
public void set(Object obj,Object value)//设置对象属性内容
  1. 实例化对象
      1)无参构造实例化对象,即使用newInstance()方法。
package N_Reflect.Ex02;

import java.time.Period;
class Person{
    private String name;
    private int age;

//    public Person(String name,int age) {
//        super();
//    }

    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 String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class Ex_02 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        //获取字节码文件对象
        Class clazz = Class.forName("N_Reflect.Ex02.Person");
        //创建对象
        Person per = null;
        //	如果没有无参的构造方法会报错,所以要求必须要有无参的构造方法
        //(默认有一个无参的构造方法,如果新增一个有参的构造方法,
        // 还需要使用无参的必须再定义一个无参的构造方法)。
        per = (Person) clazz.newInstance();//实例化对象。
        per.setAge(20);
        per.setName("耶耶");
        System.out.println(per);
    }
}

  2)有参构造实例化对象,getConstructors()和.newInstance()结合使用。

package N_Reflect.Ex03;

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

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 String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class Ex_03 {
    //通过有参构造方法
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
        //获取字节码文件对象
        Class clazz = Class.forName("N_Reflect.Ex03.Person");
        Constructor[] constructors = clazz.getConstructors();
        Person per = (Person) constructors[0].newInstance("zhangsan", 20);//参数对应构造方法的参数
        System.out.println(per);
    }
}

  3)获取所有实现的接口,getInterfaces()方法使用。

package N_Reflect.Ex04;

interface Country{}

interface City{}

class Person implements Country, City{
    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 String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class Ex_04 {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取所实现的全部接口
        Class clazz = Class.forName("N_Reflect.Ex04.Person");
        Class[] interfaces = clazz.getInterfaces();
        for (Class anInterface : interfaces) {
            System.out.println("实现的接口名称:"+anInterface.getName());
        }
    }
}

  4)获取所有方法,getMethods()方法。

package N_Reflect.Ex05;

import java.lang.reflect.Method;

interface Country{
    public abstract void sayHello();
}

class Person implements Country {
    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 void sayHello() {
        System.out.println("say Hello......");
    }
}

public class Ex_05 {
    //获取全部方法
    public static void main(String[] args) throws ClassNotFoundException {
        //获取字节码文件
        Class clazz = Class.forName("N_Reflect.Ex05.Person");
        //获取成员方法
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            System.out.println("方法名称"+method.getName());//会有其他的Object方法,因为都继承Object。
        }
    }
}

  5)获取所有属性,.getDeclaredFields()方法。

package N_Reflect.Ex06;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

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 String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class EX_06 {
    //获取全部属性
    public static void main(String[] args) throws ClassNotFoundException {
        //获取字节码文件
        Class clazz = Class.forName("N_Reflect.Ex06.Person");
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            System.out.println("属性名称:"+ field.getName()+",属性类型:"+ field.getType()+",属性修饰符"+ Modifier.toString(field.getModifiers()));
        }
    }
}

  6)利用反射重写toString。

package N_Reflect.EX07_toString;

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

class Person{
    private String name;
    private int age;

    public Person() {

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

public class StringUtils {
    public String toString(Object obj) {
        //获取该对象的字节码文件
        Class clazz = obj.getClass();
        //创建StringBuilder对象
        StringBuilder sb = new StringBuilder();
        //获取包所在包
        Package packageName = clazz.getPackage();
        sb.append("包名:"+packageName.getName()+"\n");
        String simpleName = clazz.getSimpleName();
        sb.append("类名:"+simpleName+"\n");

        sb.append("公共的构造方法:\n");
        Constructor[] constructors = clazz.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            final String  modifier=Modifier.toString(constructor.getModifiers());
            if (modifier.contains("public")){
                sb.append(constructor.toGenericString()+"\n");//获取基本信息
            }
        }

        //获取共有成员变量
        sb.append("公共的Field:\n");
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            String modifier = Modifier.toString(field.getModifiers());
            if (modifier.contains("public")){
               sb.append(field.toGenericString()+"\n");
            }
        }
        //获取共有成员方法
        sb.append("公共的方法:\n");
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            String modifier = Modifier.toString(method.getModifiers());
            if (modifier.contains("public")){
                sb.append(method.toGenericString()+"\n");
            }
        }

        return sb.toString();
    }

    public static void main(String[] args) {
        StringUtils stringUtils = new StringUtils();
        //Object
        System.out.println(stringUtils.toString(new Object()));
        //其他方法
        Person person = new Person();
        System.out.println(stringUtils.toString(person));
    }
}

  7)模拟获取普通用户与Vip用户下载速度(●’◡’●)…。

package N_Reflect.Ex08;

import java.util.Scanner;

interface Common {
    int getDownload(int speed);
}

class Consumer implements Common {
    @Override
    public int getDownload(int speed) {
        return 128;
    }
}

class Vip implements Common{
    @Override
    public int getDownload(int speed) {
        return speed;
    }
}
public class Download {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Scanner in = new Scanner(System.in);
        System.out.println("输入用户角色:Vip/Consumer");
        String username = in.nextLine();//Vip Consumer

        int speed = 10000;

        String user = "N_Reflect.Ex08." + username;

        Common common = (Common) Class.forName(user).newInstance();

        System.out.println("userSpeed:" + common.getDownload(speed));

    }
}

  8)通过反射读取配置文件进行类的实例化。

①新建Person类

package N_Reflect.Ex09;

public class Person {
    public void sleep(){
        System.out.println("Person....sleep............");
    }
}

②新建Student类

package N_Reflect.Ex09;

public class Student {
    public void sleep(){
        System.out.println("Student....sleep............");
    }
}

③新建test.properties文件,需要注意路径,需要带包名,maven可以放在resources目录下。

	className=N_Reflect.Ex09.Student
	methodName=sleep

④新建测试类

package N_Reflect.Ex09;

import java.lang.reflect.Method;
import java.util.Properties;

public class TestSleep {
    public static void main(String[] args) throws Exception {
        //加载test.properties中的内容并存储到Properties集合。
        Properties properties = new Properties();
        properties.load(TestSleep.class.getResourceAsStream("/config/test.properties"));
        //获取数据
        String className = properties.getProperty("className");
        String methodName = properties.getProperty("methodName");
        //获取字节码文件
        Class clazz = Class.forName(className);
        //创建类的对象
        Object obj = clazz.newInstance();
        //获取指定的方法对象,
        Method method = clazz.getMethod(methodName);
        //执行该成员方法
        method.invoke(obj);//通过obj调用指定方法

    }
}

⑤修改配置文件的参数执行测试,查看变化可以根据配置文件内容进行实例化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值