文章目录
- 今天的内容
- 1.反射
- 1.1获取Class对象
- 1.2获取Constructor对象
- 1.3获取Method对象
- 1.4获取Field对象
今天的内容
1.反射【重点】
1.反射
反射很重要,咱们以后进行封装的时候都有必要书写反射,让咱们的代码具有更强普适性
Java反射是在动态的获取类, 类属性, 类方法, 类构造方法等内部一些类的信息。
反射本质就是反着来。
平常获取类 new 一个对象,现在可以通过反射来获取。
package com.qfedu.a_reflect;import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;public class Demo1 {public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {//想创建一个对象,直接newPerson 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);}public static void test(Person p) {}public static void test(Class cls) {}
}
从数据库里面查数据,但是查出来的数据要赋值一个类
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对象有三种方式:
package com.qfedu.b_class;import com.qfedu.a_reflect.Person;public class Demo1 {public static void main(String[] args) throws ClassNotFoundException {//第一种获取class对象方式//com.qfedu.a_reflect.Person 类全限定名Class<?> aClass = Class.forName("com.qfedu.a_reflect.Person");System.out.println(aClass);//第二种方式Class<Person> personClass = Person.class;System.out.println(personClass);//第三种方式Class<? extends Person> aClass1 = new Person().getClass();System.out.println(aClass1);}
}
为啥要获取一个类的字节码文件对象,因为我要获取字节码文件下面的 构造方法 方法 属性 等信息
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对象调用的
T
newInstance(Object... initargs)
使用此Constructor
对象表示的构造函数,使用指定的初始化参数来创建和初始化构造函数的声明类的新实例。
package com.qfedu.c_constructor;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);}
}
只用getConstructor(Class…parameterType);
newInstance(Object… initargs);
一个类下面有构造方法 方法 属性
1.3获取Method对象
Method[] getMethods()获取当前类或者父类的公开的所有的方法 Method[]
getDeclaredMethods()
获取当前类所有的方法,但是不能获取父类的方案Method getMethod(String name, 类<?>... parameterTypes)
返回一个方法
对象,它反映此表示的类或接口的指定公共成Method getDeclaredMethod(String name, 类<?>... parameterTypes)
返回一个方法
对象,它反映此表示的类或接口的指定声明的方法类
对象。
学一个Method下面的方法
Object
invoke(Object obj, Object… args)在具有指定参数的 方法
对象上调用此方法
对象
package com.qfedu.d_method;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类型的数据//私有话的方法getDeclaredMethodMethod 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对象
package com.qfedu.e_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);}
}