欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

反射(反射的介绍、获取源头Class、创建对象、属性和方法)

程序员文章站 2023-04-03 17:11:43
一、1. 反射的介绍1.反射的定义JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。Java反射机制,可以实现以下功能:①在运行时判断任意一个对象所属的类;②在运行时构造任意一个类的对象;③在运行时判断任意一个类所具有的成员变量和方法;④在运行时调用任意一个对象的方法;⑤生成动态代理;二、获取源头Class(重点)所有类的对象其实都是Cla...

一、 反射的介绍

1.反射的定义

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
Java反射机制,可以实现以下功能:
①在运行时判断任意一个对象所属的类;
②在运行时构造任意一个类的对象;
③在运行时判断任意一个类所具有的成员变量和方法;
④在运行时调用任意一个对象的方法;
⑤生成动态代理;

二、获取源头Class(重点)

所有类的对象其实都是Class的实例。这个 Class 实例可以理解为类的模子,就是包含了类的结构信息,类似于图纸。我们日常生活中,需要创造一个产品,如想山寨一个iphone手机,怎么办?
有三种方式可以实现:
⑴买个iphone手机,拆的七零八落的,开始山寨;
⑵到iphone工厂参观,拿到iphone磨具,开始山寨;
⑶跑到美国盗取iphone的图纸,开始山寨,最后一种最暴力,最爽。
同理,获取类的Class对象也有三种方式
⑴Class.forName(”包名.类名”) //一般尽量采用该形式
(2)类.class
(3)对象.getClass()
思考:目前我们创建对象的方式有哪写?

[1]获取Class对象

Class是一切的源头,所有伟大的事业都有一个不起眼的开头。而反射有三种出场方式
第一种方式: 对象.class

 Person person = new Person(); //对象.getClass() Class<? extends Person> aClass = person.getClass(); System.out.println(aClass.getName()); 

第二种方式: 类.class

 //类名.class Class<Person> aClass = Person.class; 

第三种方式(推荐方式): Class.forName()

// Class.forName("全限定路径")  全限定路径:包名+类名 Class<?> aClass = Class.forName("com.shsxt.reflect.Person"); 

有了class对象,我们就有了一切,这就是反射的源头,接下来就是“庖丁解牛”。

[2] 获取修饰符

获取修饰符,使用 getModifiers() 即可, Modifier 类提供了 static 方法和
常量来解码类和成员访问修饰符
反射(反射的介绍、获取源头Class、创建对象、属性和方法)

 Class<Person> aClass = (Class<Person>) Class.forName("com.shsxt.reflect.Person"); int modifiers = aClass.getModifiers(); //使用Modifier转换为相应的字符串 System.out.println(Modifier.toString(modifiers)); 

反射(反射的介绍、获取源头Class、创建对象、属性和方法)

三、创建对象

1. 构造器

根据Class对象,我们可以获得构造器,为实例化对象做准备。调用以下api即可。
反射(反射的介绍、获取源头Class、创建对象、属性和方法)

Constructor getDeclaredConstructor([参数列表.class]) 返回一个Constructor对象,这个构造器是父类或子类的共有的构造器
Constructor<?>[] getDeclaredConstructors()返回包含一个数组Constructor对象反射,这个构造器对象是自己的公有和私有的构造器

私有的属性、构造器、方法均可通过调研setAccessible(true)来打开权限。

 //获取Person的class Class<Person> personClass = Person.class; //不能获取私有的构造器,只能获取公开的构造器 Constructor<Person> constructor = personClass.getConstructor(String.class, int.class); System.out.println(constructor); Person person = constructor.newInstance("张三", 18); System.out.println(person); //可以获取私有的构造器,也可以获取公开的构造器 Constructor<Person> declaredConstructor = personClass.getDeclaredConstructor(); System.out.println(declaredConstructor); //如果是私有的,则打开权限再使用 declaredConstructor.setAccessible(true); System.out.println(declaredConstructor.newInstance()); //获取所有的公有的构造器 Constructor<?>[] constructors = personClass.getConstructors(); System.out.println(constructors.length); //获取所有的构造器  公有+私有 Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors(); System.out.println(declaredConstructors.length); 

2.实例化对象

创建对象的方式,有new克隆反序列化,再加一种,根据Class对象,使用newInstance() 或者构造器实例化对象。调用以下api即可

// 通过反射 //   clz newInstance() //     通过获取构造器, 利用构造器去创建对象 public class NewInstance { public static void main(String[] args) throws Exception { //1、获取Class Class<Person> aClass = (Class<Person>)Class.forName("com.shsxt.reflect.Person"); //2、创建对象,必须保证空构造存在.而且只能是调用空构造,属性是没有数据的 //(一)创建对象的方式一: Person person = aClass.newInstance(); System.out.println(person); // (二)创建对象方式二:无参 // 获取构造器对象(无参构造) Constructor<Person> constructor = aClass.getConstructor(); //执行构造器,获取Bean对象 Person person1 = constructor.newInstance(); System.out.println(person1); // (二)创建对象方式三:有参  获取指定构造器  获取带参构造  String类型,  int类型 Constructor<Person> constructor1 = aClass.getConstructor(String.class, int.class); Person person2 = constructor1.newInstance("张三", 18); System.out.println(person2); //(三)创建对象的方式四:通过私有构造器创建 // 获取私有的构造器 Constructor<Person> declaredConstructor = aClass.getDeclaredConstructor(); //打开权限 declaredConstructor.setAccessible(true); Person person3 = declaredConstructor.newInstance(); System.out.println(person3); Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors(); } } 

反射(反射的介绍、获取源头Class、创建对象、属性和方法)
注意:newInstance()是调用空构造如果空构造不存在,会出现异常。由此可知,使用其他构造器创建对象比较麻烦,使用空构造非常简单。确保空构造存在

3. 父类与接口

反射(反射的介绍、获取源头Class、创建对象、属性和方法)
定义Person类,Student类继承Person类

 //获取Student的Class Class<Student> studentClass = Student.class; //student的父类 Class<? super Student> superclass = studentClass.getSuperclass(); System.out.println(superclass); 

反射(反射的介绍、获取源头Class、创建对象、属性和方法)

四、属性和方法

1. 属性(获得属性及设置属性值)

获取所有属性(包括父类或接口) ,使用 Field 即可操作, Field 作为描述属性的对象
反射(反射的介绍、获取源头Class、创建对象、属性和方法)

/**
Class
属性的操作: Field对象
 */ public class ReflectField { public static void main(String[] args) throws Exception { //获取Class对象 Class<Student> aClass = Student.class; Student student = aClass.newInstance(); Field id = aClass.getField("id"); // 属性的权限, 类型, 名称 // 通过id对象获取 studnet对象的 id属性值 int idValue = (int)id.get(student); // 获取某个对象的这个属性的值 System.out.println(idValue);//10 //要获取一个对象的属性值 Field money = aClass.getDeclaredField("money"); // 如果是私有属性则打开权限 money.setAccessible(true); //获取指定对象的属性 System.out.println(money.get(student));//100 //修改一个对象的属性值 money.set(student,2999); System.out.println(student.getMoney());//2999 //获取money属性的类型 System.out.println(money.getType());//int System.out.println(Modifier.toString(money.getModifiers()));//private //获取属性名称 System.out.println(money.getName());//money //获取静态属性scoolName Field scoolName = aClass.getField("scoolName"); // 静态的内容 尽量不要和对象关联  对象参数设为null scoolName.set(null,"sxt"); System.out.println(Student.scoolName);//sxt } } 

2.方法(通过反射执行方法)

获取所有方法(包括父类或接口),使用 Method 即可。 Method 即作为描述方法的对象。
反射(反射的介绍、获取源头Class、创建对象、属性和方法)
实体类Person,Student的父类

public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public Person() { } 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 void testFatherPublict(){ System.out.println("Person.testFatherPublict"); } private void testFatherPrivate(){ System.out.println("Person.testFatherPrivate"); } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } } 

实体类Student

public class Student extends Person{ public int id; private int money; public static String scoolName; public Student() { this.id = 10; this.money = 100; } public Student(int id, int money) { this.id = id; this.money = money; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getMoney() { return money; } public void test(String str){ System.out.println(str); } public void setMoney(int money) { this.money = money; } public void testSelefPublic(){ System.out.println("Student.testSelefPublic"); } private void testSelefPrivate(){ System.out.println("Student.testSelefPrivate"); } @Override public String toString() { return "Student{" + "id=" + id + ", money=" + money + '}'; } } 
 //获取Class对象 Class<Student> studentClass = Student.class; Student student = studentClass.newInstance(); //获取方法  方法的对象 //方法名  、参数类型.class Method method = studentClass.getMethod("test", String.class); System.out.println(method); //执行方法 // 通过student执行它的 m1对象中的方法, 将 "helloworld" 作为实参,执行这个方法得到的结果, invoke的返回值 Object o = method.invoke(student, "helloworld"); //System.out.println(o); //获取返回值 Class<?> type = method.getReturnType(); System.out.println(type); Method method1 = studentClass.getDeclaredMethod("testSelefPrivate"); //打开方法的权限 method1.setAccessible(true); method1.invoke(student); 

通过反射获取方法

 //获取Class对象 Class<Student> studentClass = Student.class; Student student = studentClass.newInstance(); //获取方法  方法的对象 //方法名  、参数类型.class Method method = studentClass.getMethod("test", String.class); System.out.println(method); //执行方法 // 通过student执行它的 m1对象中的方法, 将 "helloworld" 作为实参,执行这个方法得到的结果, invoke的返回值 Object o = method.invoke(student, "helloworld"); //System.out.println(o); //获取返回值 Class<?> type = method.getReturnType(); System.out.println(type); Method method1 = studentClass.getDeclaredMethod("testSelefPrivate"); //打开方法的权限 method1.setAccessible(true); method1.invoke(student); 

反射(反射的介绍、获取源头Class、创建对象、属性和方法)

五、数组(仅了解)

操作数组需要借助Array类

//1、创建数组  Object obj = Array.newInstance(int.class, 5); //2、获取大小  if(obj.getClass().isArray()){ //3、判断是否为数组  System.out.println(Array.getLength(obj)); //4、设置值  Array.set(obj,0, 100); //5、获取值  System.out.println(Array.get(obj,0)); } 

本文地址:https://blog.csdn.net/weixin_44911308/article/details/108013211