反射
JAVA反射机制是在运行状态中,对于任意一个类(class文件),都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象方法的功能称为java语言的反射机制。
动态获取类中信息,就是java反射。可以理解为对类的解剖。
如果想要对指定名称的字节码文件进行加载并获取其中的内容并调用,这时就使用到了反射技术。
P.S.
所谓的框架就是对外提供一些接口,也就是功能扩展的标准,由实现类按照这个接口标准去实现。框架内部如果需要操纵这些实现类的对象完成某些操作,那么只需要把这些实现类的全名(包名+类名)写在某个配置文件中,框架代码只需要读取这个配置文件,就可以获取这个实现类的字节码文件,然后利用反射技术创建这个实现类的对象并且调用相应的方法完成一些操作。
用于描述字节码的类就是Class类,创建对象,可以提取字节码文件中的内容,如字段、构造函数、一般函数。该类就可以获取字节码文件中的所有内容,那么反射就是依靠该类完成的。想要对一个类文件进行解剖,只要获取到该类的字节码文件对象即可。
属性
field(字段)
method(方法)
construction(构造函数)
字节码
当源程序中用到类时,首先要从硬盘把这个类的那些二进制代码,
一个类编译成class放在硬盘上以后,就是一些二进制代码,要把这些二进制代码加载到内存中里面来,再用这些字节码去复制出一个一个对象来
获取Class对象的三种方式
1,Object类的getClass()方法
Person p = new Person();
Class c = p.getClass();
2,数据类型的静态属性
class Class c2 = Person.class;
3,Class中的静态方法:::public static Class forName(String className)
Class c3 = Class.forName(“全路径(带包名)”);
注意: 一般情况:开发中使用第三种,因为第三种是一个字符串,而不是一个具体的类名,这样我们就可以把字符串配置到配置文件中。
Person.java
package reflect;
public class Person
{
private int age;
private String name;
public Person(int age,String name){
super();
this.age = age;
this.name = name;
System.out.println("Person param run..." + this.name + ":" + this.age);
}
public Person(){
super();
System.out.println("person run");
}
public void show(){
System.out.println(name + "...show run..." + age);
}
private void privateMethod(){
System.out.println("method run");
}
public void paramMethod(String str,int num){
System.out.println("paramMethod run..." + str + ":" + num);
}
public static void staticMethod(){
System.out.println("static method run...");
}
}
import reflect.Person;
//要想要对字节码文件进行解剖,必须要有字节码文件对象。
public class ReflectDemo
{
public static void main(String[] args) throws ClassNotFoundException {
getClassObject_1();
System.out.println("--------------------");
getClassObject_2();
System.out.println("--------------------");
getClassObject_3();
}
/*
* 获取字节码对象的方式:
* 方式一:Object类中的getClass()方法的。
* 想要用这种方式,必须要明确具体的类,并创建对象。
* 麻烦。
*/
public static void getClassObject_1(){
Person p = new Person();
Class clazz = p.getClass();
Person p1 = new Person();
Class clazz1 = p1.getClass();
System.out.println(clazz == clazz1);
}
/*
* 方式二:任何数据类型都具备一个静态的属性.class来获取其对应的Class对象。
* 相对简单,但是还是要明确用到类中的静态成员。
* 还是不够扩展。
*/
public static void getClassObject_2(){
Class clazz = Person.class;
Class clazz1 = Person.class;
System.out.println(clazz == clazz1);
}
/*
* 方式三:只要通过给定的类的字符串名称就可以获取该类,更为扩展。
* 可以用Class类中的方法完成。
* 该方法就是forName。
* 这种方法只要有名称即可,更为方便,扩展性更强。
*/
public static void getClassObject_3() throws ClassNotFoundException {
//可以把类的字符串名称写到配置文件中,然后读取出来。
String className = "reflect.Person";
Class clazz = Class.forName(className);
System.out.println(clazz);
}
}
Class类是没有构造方法的, 因此只能通过方法获取类实例对象。
步骤
1,查找并加载指定名字的字节码文件进内存,并被封装成Class对象。
2,通过Class对象的newInstance方法创建该Class对应的类实例。
3,调用newInstance()方法会去使用该类的空参数构造函数进行初始化。
注:newInstance() 创建此 Class 对象所表示的类的一个新实例。
package reflect;
public class Person {
private String name;
private int age;
private String address;
public Person() {
}
public Person(String name, int age, String adderss) {
this.name = name;
this.age = age;
this.address = adderss;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
private Person(String name) {
this.name = name;
}
public void show() {
System.out.println("hello");
}
public void method(String s) {
System.out.println("method::" + s);
}
public String getString(String s, int i) {
return s + "::" + i;
}
private void method2(){
System.out.println("私有方法");
}
public String toString() {
return name + "::" + age + "::" + address;
}
}
package reflect;
import java.lang.reflect.Constructor;
//通过反射获取构造方法并使用。
public class ReflectUsing {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象
Class c = Class.forName("reflect.Person");
// 获取所有构造方法
Constructor[] cons = c.getDeclaredConstructors();
for (Constructor con : cons) {
System.out.println(con);
}
// 获取单个构造方法
Constructor con = c.getConstructor();//返回的是构造方法对象
Object obj = con.newInstance();
System.out.println(obj);
}
}
package reflect;
import java.lang.reflect.Constructor;
public class ReflectPractice2 {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象
Class c = Class.forName("reflect.Person");
// 获取带参构造器
Constructor con = c.getConstructor(String.class, int.class, String.class);//返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法
// 通过带参构造方法对象创建对象
Object obj = con.newInstance("QI",23,"hebei");
System.out.println(obj);
}
}
package reflect;
import java.lang.reflect.Constructor;
// 通过反射获取私有构造方法并使用
public class ReflectPractice3 {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象
Class c = Class.forName("reflect.Person");
//获取私有构造方法
Constructor con = c.getDeclaredConstructor(String.class);//返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
//设置私有方法可访问
con.setAccessible(true);
//用该私有构造方法创建对象
Object obj = con.newInstance("qi");
System.out.println(obj);
}
}
了解谨记Class 方法
forName(String className) ` 返回与带有给定字符串名的类或接口相关联的 Class 对象。
getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
Field类
Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。
Method类
概念
Method类代表某个类中的一个成员方法。调用某个对象身上的方法,要先得到方法,再针对某个对象调用。
JAVA反射机制是在运行状态中,对于任意一个类(class文件),都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象方法的功能称为java语言的反射机制。
动态获取类中信息,就是java反射。可以理解为对类的解剖。
如果想要对指定名称的字节码文件进行加载并获取其中的内容并调用,这时就使用到了反射技术。
P.S.
所谓的框架就是对外提供一些接口,也就是功能扩展的标准,由实现类按照这个接口标准去实现。框架内部如果需要操纵这些实现类的对象完成某些操作,那么只需要把这些实现类的全名(包名+类名)写在某个配置文件中,框架代码只需要读取这个配置文件,就可以获取这个实现类的字节码文件,然后利用反射技术创建这个实现类的对象并且调用相应的方法完成一些操作。
用于描述字节码的类就是Class类,创建对象,可以提取字节码文件中的内容,如字段、构造函数、一般函数。该类就可以获取字节码文件中的所有内容,那么反射就是依靠该类完成的。想要对一个类文件进行解剖,只要获取到该类的字节码文件对象即可。
属性
field(字段)
method(方法)
construction(构造函数)
字节码
当源程序中用到类时,首先要从硬盘把这个类的那些二进制代码,
一个类编译成class放在硬盘上以后,就是一些二进制代码,要把这些二进制代码加载到内存中里面来,再用这些字节码去复制出一个一个对象来
获取Class对象的三种方式
1,Object类的getClass()方法
Person p = new Person();
Class c = p.getClass();
2,数据类型的静态属性
class Class c2 = Person.class;
3,Class中的静态方法:::public static Class forName(String className)
Class c3 = Class.forName(“全路径(带包名)”);
注意: 一般情况:开发中使用第三种,因为第三种是一个字符串,而不是一个具体的类名,这样我们就可以把字符串配置到配置文件中。
Person.java
package reflect;
public class Person
{
private int age;
private String name;
public Person(int age,String name){
super();
this.age = age;
this.name = name;
System.out.println("Person param run..." + this.name + ":" + this.age);
}
public Person(){
super();
System.out.println("person run");
}
public void show(){
System.out.println(name + "...show run..." + age);
}
private void privateMethod(){
System.out.println("method run");
}
public void paramMethod(String str,int num){
System.out.println("paramMethod run..." + str + ":" + num);
}
public static void staticMethod(){
System.out.println("static method run...");
}
}
import reflect.Person;
//要想要对字节码文件进行解剖,必须要有字节码文件对象。
public class ReflectDemo
{
public static void main(String[] args) throws ClassNotFoundException {
getClassObject_1();
System.out.println("--------------------");
getClassObject_2();
System.out.println("--------------------");
getClassObject_3();
}
/*
* 获取字节码对象的方式:
* 方式一:Object类中的getClass()方法的。
* 想要用这种方式,必须要明确具体的类,并创建对象。
* 麻烦。
*/
public static void getClassObject_1(){
Person p = new Person();
Class clazz = p.getClass();
Person p1 = new Person();
Class clazz1 = p1.getClass();
System.out.println(clazz == clazz1);
}
/*
* 方式二:任何数据类型都具备一个静态的属性.class来获取其对应的Class对象。
* 相对简单,但是还是要明确用到类中的静态成员。
* 还是不够扩展。
*/
public static void getClassObject_2(){
Class clazz = Person.class;
Class clazz1 = Person.class;
System.out.println(clazz == clazz1);
}
/*
* 方式三:只要通过给定的类的字符串名称就可以获取该类,更为扩展。
* 可以用Class类中的方法完成。
* 该方法就是forName。
* 这种方法只要有名称即可,更为方便,扩展性更强。
*/
public static void getClassObject_3() throws ClassNotFoundException {
//可以把类的字符串名称写到配置文件中,然后读取出来。
String className = "reflect.Person";
Class clazz = Class.forName(className);
System.out.println(clazz);
}
}
Class类是没有构造方法的, 因此只能通过方法获取类实例对象。
步骤
1,查找并加载指定名字的字节码文件进内存,并被封装成Class对象。
2,通过Class对象的newInstance方法创建该Class对应的类实例。
3,调用newInstance()方法会去使用该类的空参数构造函数进行初始化。
注:newInstance() 创建此 Class 对象所表示的类的一个新实例。
package reflect;
public class Person {
private String name;
private int age;
private String address;
public Person() {
}
public Person(String name, int age, String adderss) {
this.name = name;
this.age = age;
this.address = adderss;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
private Person(String name) {
this.name = name;
}
public void show() {
System.out.println("hello");
}
public void method(String s) {
System.out.println("method::" + s);
}
public String getString(String s, int i) {
return s + "::" + i;
}
private void method2(){
System.out.println("私有方法");
}
public String toString() {
return name + "::" + age + "::" + address;
}
}
package reflect;
import java.lang.reflect.Constructor;
//通过反射获取构造方法并使用。
public class ReflectUsing {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象
Class c = Class.forName("reflect.Person");
// 获取所有构造方法
Constructor[] cons = c.getDeclaredConstructors();
for (Constructor con : cons) {
System.out.println(con);
}
// 获取单个构造方法
Constructor con = c.getConstructor();//返回的是构造方法对象
Object obj = con.newInstance();
System.out.println(obj);
}
}
package reflect;
import java.lang.reflect.Constructor;
public class ReflectPractice2 {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象
Class c = Class.forName("reflect.Person");
// 获取带参构造器
Constructor con = c.getConstructor(String.class, int.class, String.class);//返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法
// 通过带参构造方法对象创建对象
Object obj = con.newInstance("QI",23,"hebei");
System.out.println(obj);
}
}
package reflect;
import java.lang.reflect.Constructor;
// 通过反射获取私有构造方法并使用
public class ReflectPractice3 {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象
Class c = Class.forName("reflect.Person");
//获取私有构造方法
Constructor con = c.getDeclaredConstructor(String.class);//返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
//设置私有方法可访问
con.setAccessible(true);
//用该私有构造方法创建对象
Object obj = con.newInstance("qi");
System.out.println(obj);
}
}
了解谨记Class 方法
forName(String className) ` 返回与带有给定字符串名的类或接口相关联的 Class 对象。
getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
Field类
Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。
Method类
概念
Method类代表某个类中的一个成员方法。调用某个对象身上的方法,要先得到方法,再针对某个对象调用。