java中的反射机制
- 什么是反射 为什么要使用反射 什么情况下使用反射
- 获取Class对象的常用方法
- 利用反射获取类的构造方法
- 利用反射获取类的方法
- 利用发射获取类的属性(成员变量)
- 利用反射创建对象
- 利用反射调用类的方法
- 利用反射访问类的属性
什么是反射 为什么要使用反射 什么情况下使用反射
反射机制指的是程序在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法。
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
jdk 1.6 版本引入了 反射机制,就是用来动态的创建对象,调用类的方法,或者访问类的属性的一种机制(思路)就相当于用反射给 java静态语言打了动态语言的补丁,有了反射之后就很容易 解决上述问题了
java 是静态语言
静态语言是指在编译时变量的du数据类型即可zhi确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型。例如:C++、Java、Delphi、C#等。
动态语言是在运行时确定数据类型的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。例如:Python、Ruby、Perl等。
现在一般很少这样划分程序语言了
js 是动态语言 js 就能在程序的运行期 根据指定的参数创建指定的对象或者调用方法或者访问属性
动态类型语言 一般是脚本语言,比如说Perl、Ruby、Python、PHP、JavaScript,可以更快地编写代码,不必每次都指定类型,做type checking是在run-time的时候去做的。优点是可能代码开发快,但是维护难(但是脚本语言平常写的代码量应该不太多,还比较好debug和修改)
获取Class对象的常用方法
每个java的类在jvm加载之后 都会自动在内存中创建该类对应的Class对象
我们要做的事就是使用特定的方式 去获取这个对象就可以了
package com.aaa.demo;
/**
* @Author Lst
* @Date 2021/1/4 18:25
* @Version 1.0
* 获取class对象的三种方式
*/
public class Person01 {
public static void main(String[] args) throws ClassNotFoundException {
// 第一种方式 直接访问类的class属性
Class clazz01 = Person01.class;
System.out.println(clazz01);
// 第二种方式 调用类的对象getClass方法
Person01 person01 = new Person01();
Class clazz02 = person01.getClass();
System.out.println(clazz02);
// 第三种方式 调用 class 类的静态方法 forName
Class clazz3 = Class.forName("com.aaa.demo.Person01");
System.out.println(clazz3);
}
}
利用反射或者类的构造方法
package com.aaa.demo;
import java.lang.reflect.Constructor;
/**
* @Author Lst
* @Date 2021/1/5 10:39
* @Version 1.0
* 利用反射获取类的构造方法对象
*/
public class Person02 {
public Person02() {
System.out.println("默认无参构造");
}
public Person02(String name) {
System.out.println("默认有一个参数的构造方法");
}
private Person02(String name, Integer age) {
System.out.println("有两个参数的私有构造方法");
}
public static void main(String[] args) throws NoSuchMethodException {
// 获取类的class对象
Class clazz = Person02.class;
System.out.println("获取类的所有的公共构造方法");
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
System.out.println("打印类所有的声明的构造方法");
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor declaredConstructor : declaredConstructors) {
System.out.println(declaredConstructor);
}
// 获取指定的构造方法的对象
Constructor constructor = clazz.getConstructor(String.class);
System.out.println("获取有一个参数的公共的构造方法");
System.out.println(constructor);
// 获取 指定的构造方法
Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class, Integer.class);
System.out.println("获取有两个参数的私有构造方法");
System.out.println(declaredConstructor);
}
}
利用反射获取类的方法
package com.aaa.demo;
import java.lang.reflect.Method;
/**
* @Author Lst
* @Date 2021/1/5 13:40
* @Version 1.0
* 利用反射获取类的方法
*/
public class Person03 {
public void info() {
System.out.println("没有参数的公共的方法");
}
public void info(String name) {
System.out.println("只有一个参数的公共方法");
}
private void info(String name, Integer age) {
System.out.println("有两个参数的私有方法");
}
public static void main(String[] args) throws NoSuchMethodException {
// 获取类的 class 对象
Class clazz = Person03.class;
// 获取类的方法对象
System.out.println("能获取到所有公共的方法,包含父类中的公共的方法");
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("获取类声明过 所有的方法, 不包含父类中的方法");
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
System.out.println("获取类的有一个 String类型参数并且方法名为 info 的公共的方法");
Method method = clazz.getMethod("info",String.class);
System.out.println(method);
System.out.println("获取类的有 String类型参数跟 Integer类型的参数 私有的方法名为 info");
Method method1 = clazz.getDeclaredMethod("info",String.class,Integer.class);
System.out.println(method1);
}
}
利用发射获取类的属性(成员变量)
package com.aaa.demo;
import java.lang.reflect.Field;
import java.util.Arrays;
/**
* @Author Lst
* @Date 2021/1/5 13:58
* @Version 1.0
* 利用发射获取类的属性(成员变量)
*/
public class Person04 extends Person01 {
private String name;
public Integer age;
public static void main(String[] args) throws Exception {
// 获取类的Class对象
Class clazz = Person04.class;
// 获取属性的方法
System.out.println("获取所有公共的属性,也可以获取父类中的公共属性");
Field[] clazzFields = clazz.getFields();
for (Field clazzField : clazzFields) {
System.out.println(clazzField);
}
System.out.println("获取所有公共的属性,不包含父类中的公共属性");
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
// 获取指定属性名叫age的公共的属性
System.out.println("获取属性名为age");
Field field = clazz.getField("age");
System.out.println(field);
// 获取指定属性名叫name的私有的属性
System.out.println("获取指定属性名叫name的私有的属性");
Field name = clazz.getDeclaredField("name");
System.out.println(name);
}
}
利用反射创建对象
package com.aaa.demo;
import java.lang.reflect.Constructor;
/**
* @Author Lst
* @Date 2021/1/5 14:13
* @Version 1.0
* 利用反射创建对象
*/
public class Person05 {
public Person05() {
System.out.println("默认无参构造");
}
public Person05(String name) {
System.out.println("有一个String 类型参数的公共构造");
}
public static void main(String[] args) throws Exception {
// 获取类的Class对象
Class clazz = Class.forName("com.aaa.demo.Person05");
// 第一种方式创建对象 类必须要有默认无参构造方法
Object p1 = clazz.newInstance();
System.out.println(p1);
// 第二种方式 通过调用类的构造方法对象的方法
Constructor constructor = clazz.getConstructor(String.class);
Object p2 = constructor.newInstance("张三");
System.out.println(p2);
}
}
利用反射调用类的方法
package com.aaa.demo;
import java.lang.reflect.Method;
/**
* @Author Lst
* @Date 2021/1/5 13:40
* @Version 1.0
* 利用反射调用类的方法
*/
public class Person06 {
public String info() {
System.out.println("没有参数的公共的方法");
return "李松涛";
}
public void info(String name) {
System.out.println("只有一个参数的公共方法");
}
private void info(String name, Integer age) {
System.out.println("有两个参数的私有方法");
}
public static void main(String[] args) throws Exception {
// 获取类的class对象
Class clazz = Person06.class;
// 创建Person06对象
Object person06 = clazz.newInstance();
// 获取Person06默认无参的 info方法
Method infoMethod = clazz.getMethod("info");
// 调用infoMethod 的方法
Object result = infoMethod.invoke(person06);
System.out.println(result);
// 调用有参数的 方法
Method info = clazz.getDeclaredMethod("info", String.class, Integer.class);
info.invoke(person06, "张三", 19);
}
}
利用反射访问类的属性
package com.aaa.demo;
import java.lang.reflect.Field;
/**
* @Author Lst
* @Date 2021/1/5 13:58
* @Version 1.0
* 利用反射访问类的属性
*/
public class Person07 extends Person01 {
private String name;
public Integer age;
public static void main(String[] args) throws Exception {
// 获取类的Class对象
Class clazz = Person07.class;
// 创建对象
Object o = clazz.newInstance();
// 获取类的属性名 为age的属性
Field age = clazz.getField("age");
// 为age的filed对象设置值
age.set(o, 19);
// 获取 age 属性的值
System.out.println(age.get(o));
Class clazz02 = Person01.class;
Field info = clazz02.getField("info");
// 获取私有的属性
Field name = clazz.getDeclaredField("name");
// 设置忽略访问级别
name.set(o, "zhangsan");
System.out.println(name.get(o));
}
}
再别的类访问 私有的属性 跟方法的话
package com.aaa.demo;
import java.lang.reflect.Field;
/**
* @Author Lst
* @Date 2021/1/5 19:31
* @Version 1.0
*/
public class Person08 {
public static void main(String[] args) throws Exception{
// 获取类的对象
Class clazz = Person07.class;
// 创建对象
Object o = clazz.newInstance();
// 获取类的属性名age的属性
Field age = clazz.getDeclaredField("name");
// 设置忽略
age.setAccessible(true);
age.set(o,"lyx");
System.out.println(age.get(o));
}
}