Bootstrap

反射 及获取对象的方法

目录:

1、反射

1.1  获取Class对象

1.2  获取Construtor对象

1.3  获取Method对象

1.4  获取Field对象

1、反射

反射很重要,我们以后进行封装的时候都有必要书写反射,让我们的代码具有更强普适性

Java反射是在动态的获取类,类属性,类方法,类构造方法等内部一些类的信息。

反射本质就是反着来,平常获取类   new一个对象,现在可以通过反射来获取。

想创建一个对象,直接new    例:

Person  person  =  new  Person ( );

今天再学一种方式  使用反射的方法获取一个类的对象

【Java执行原理:先编译  后执行,编译之后的文件叫Person.class  编译之后所有东西(类的属性,类的构造方法,类的成员方法)都在Person.class文件中,这个文件就变成了一个类对象了】

        //personClasss里面有类的所有的信息
        Class<Person> personClass = Person.class;
        //getConstructor获得无参构造方法
        //Constructor  把无参构造方法封装给以一个对象
        Constructor<Person> constructor = personClass.getConstructor(null);
        //要无参构造干嘛?可以通过构造方法创建对象!!!
        Person person1 = constructor.newInstance(null);


从数据库里面查数据,但是查出来的数据要赋值一个类
new admin ();
new goods();
new order();
三个类对应这数据库里面这三张表
admin表:
    name   pwd
    狗蛋      123
goods表:
    name   price
    汽车    78.9
order:
    name   status
    汽车    已付款
class BasweDao {
public List<T>  query (Class cls) {
    获取了name pwd  price   status
    值已经获取出来
    //得把这些值赋值给实体类
    //Admin admin = new Admin();
    //只能对admin赋值了,其他类不能赋值,这就不叫封装了,封装的目的是具有普适性
    Constructor<T> cst = cls.getConstructor(null);
    T t = cst.newInstance(null);
    
}
}
Admin.class
query(Admin.class);
query(Goods.class);
query(Order.class);

1.1、获取Class对象

为啥要获取Class对象?因为有了class对象才能找关于类的属性,方法 , 构造方法

Java可以将.java文件编译成.class文件,这个.calss文件中包含了原始文件中的所有的信息

.class文件会被类加载器加载到虚拟机中,可以通过.class文件获取原始类中的所有的信息

随之产生一个Class类对象。将Person.class变成了一个Class对象了

获取一个类的Class对象有三种方式:

1、Class.forName("com.qf.a__reflect.Person")

"com.qf.a__reflect.Person": 类全限定名

2、 Person.class3、new  Person( ).getClass( )

1.2、获取Constructor对象

和一个类中的构造方法有关系。构造方法类对象

Constructor<?>[]getConstructors()返回包含一个数组 Constructor对象反射由此表示Class的所有公共构造 方法对象。
Constructor<?>[]getDeclaredConstructors()返回一个反映 Constructor对象表示的类声明的所有 Constructor对象的数组
Constructor<T>getConstructor(Class<?>... parameterTypes)返回一个 Constructor对象,该对象反映 Constructor对象表示的类
Constructor<T>getDeclaredConstructor(类<?>... parameterTypes)返回一个 Constructor对象,该对象反映 Constructor对象表示的类或接口的指定 构造方法对象

以上的方法都是Class对象调用的

下面这个方法是Construct对象调用的

import com.qfedu.a_reflect.Person;

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

public class Demo1 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1.获取一个类对应的class对象
        Class<Person> personClass = Person.class;
        //2.再拿class对象获取构造方法对象
        Constructor<?>[] constructors = personClass.getConstructors();
        System.out.println(constructors);//内存地址
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);

        }
        System.out.println("-========");
        //3.获取一个类所有的构造方法对象
        Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        //4.获取单个的constructor对象
        //参数是个null  就证明获取的是无参的
        Constructor<Person> constructor = personClass.getConstructor(null);
        System.out.println(constructor);//Person();
        System.out.println("----------");
        //5获取带有字符串类型的有参构造方法
        //参数Class 对象 怎么将String转为Class对象
        Constructor<Person> constructor1 = personClass.getConstructor(String.class);
        System.out.println(constructor1);//Person(String name)
        Constructor<Person> constructor2 = personClass.getConstructor(String.class, int.class);
        System.out.println(constructor2);//Person(String name)
        //不能的!!!
//        Constructor<Person> constructor3 = personClass.getConstructor(int.class);
//        System.out.println(constructor3);//Person(int name)
        //6.获取私有化的构造方法
        Constructor<Person> declaredConstructor = personClass.getDeclaredConstructor(int.class);
        System.out.println(declaredConstructor);

        //newInstance(Object... parameter)  是Constructor对象调用的
        //不是calss对象调用的  通过构造方法对象实例化一个对象出来
        Person person = constructor.newInstance(null);
        System.out.println(person);
        //如果有参的构造方法 有参构造方法可以传值
        Person person1 = constructor1.newInstance("狗蛋");
        System.out.println(person1);
        Person person2 = constructor2.newInstance("老邢", 18);
        System.out.println(person2);
    }
}

1.3、获取Method对象

Method[]getMethods()获取当前类或者父类的公开的所有的方法
Method[]getDeclaredMethods()获取当前类所有的方法,但是不能获取父类的方案
MethodgetMethod(String name, 类<?>... parameterTypes)返回一个 方法对象,它反映此表示的类或接口的指定公共成
MethodgetDeclaredMethod(String name, 类<?>... parameterTypes)返回一个 方法对象,它反映此表示的类或接口的指定声明的方法 对象。

学一个Method下面的方法

Objectinvoke(Object obj, Object... args)在具有指定参数的 方法对象上调用此 方法对象
import com.qfedu.a_reflect.Person;

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

public class Demo1 {
    public static void main(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        Class<Person> personClass = Person.class;
        //通过class对象获取一个类下面方法对象Method
        //打印的本类公开的方法和父类的方法
        Method[] methods = personClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("==========");
        //获取本类的所有的方法
        Method[] declaredMethods = personClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {

            System.out.println(declaredMethod);
        }
        //获取一个方法  第一个参数  String方法的名字,第二个参数 方法的参数的数据类型
        Method eat = personClass.getMethod("eat", null);
        System.out.println(eat);//无参的eat方法
        Method eat1 = personClass.getMethod("eat", String.class);
        System.out.println(eat1);//有参的eat方法 参数string类型的数据

        //私有话的方法getDeclaredMethod
        Method sleep = personClass.getDeclaredMethod("sleep", null);
        System.out.println(sleep);
        //方法对象获取以后干嘛?
        //方法要被调用  使用Method对象调用invoke这个方法
        //第一个Object 是你得告诉我在那个对象下面调用

        //Object... args  是方法的参数的实参!!!
        //invoke(Object obj, Object... args)在具有指定参数的 `方法`对象上调用此 `方法`对象
        Person person = personClass.newInstance();
        //方法对象自己执行方法
        eat.invoke(person, null);
        eat1.invoke(person, "狗子");

        //证明权限不够!!!咋办 接近不了
        //can not access a member
        //咋办,让它接近就可以啦。 暴力反射
        sleep.setAccessible(true);
        sleep.invoke(person, null);
    }
}

总结:

getMethod(string name, class<?> ... parameterType);
调用
invoke(Object obj, Object....paramter)

1.获取三种方式
    Class.forName("包名+ 类名");
    类.class
    对象.getClass()
2.获取构造方法对象
    class对象.getConstructor();
    construct对象.newInstance();根据构造方法实例化对象
3.获取方法对象
    class对象.getMethod(String name, Class<?> ...parameterType);
    method对象.invoke(Object obj, Object... initargs);

类下面还有成员变量

Field

1.4获取Field对象

import com.qfedu.a_reflect.Person;

import java.lang.reflect.Field;

public class Demo1 {
    public static void main(String[] args) throws NoSuchFieldException, InstantiationException, IllegalAccessException {
        //属性是在一个类下面,也要Class对象获取属性对象
        Class<Person> personClass = Person.class;
        //getFields获取公开的属性
        Field[] fields = personClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("===========");
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {

            System.out.println(declaredField);
        }
        //获取一个属性对象 参数是属性的名字
        Field name = personClass.getField("name");
        System.out.println(name);
        //能不能使用getField方法获取私有的属性或者默认的属性?不能!!
//        Field age = personClass.getField("age");
//        System.out.println(age);
        Field age = personClass.getDeclaredField("age");
        System.out.println(age);
        Field sex = personClass.getDeclaredField("sex");
        System.out.println(sex);
        //属性对象可以获取的,获取以后干嘛?属性是用来赋值的
        //对象属性进行赋值  set方法
        Person person = personClass.newInstance();
        name.set(person, "狗子");
        System.out.println(person);
        //暴力反射
        age.setAccessible(true);
        age.set(person, 12);
        System.out.println(person);

    }
}

;