反射
概念
Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。
这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制
Class
Class 类的实例表示正在运行的 Java 应用程序中的类和接口
package com.demo;
/**
1.获取Class类的对象
① forName(String className)
注意: 参数必须是类的完全限定名。
② .class
③ getClass()
*/
public class 反射概述 {
public static void main(String[] args) throws ClassNotFoundException {
Person p = new Person();
// p.show();
Class clazz = p.getClass();
System.out.println(clazz);
Class clazz1 = Person.class;
System.out.println(clazz1);
//Person 简名
Class clazz2 = Class.forName("com.demo.Person");
System.out.println(clazz2);
}
}
class Person{
String name;
int age;
public void show(){}
}
Class类对象的获取
① forName(String className)
② .class
③ getClass()
类的加载
1.类加载过程:按需加载,并且只加载一次。
如果需要用到该类,在方法区中查找是否有该类存在,如果存在,直接使用,如果不存在,将硬盘
上.class通过类加载器加载进内存。 将.class文件转换成Class类的对象。该对象只有一个,该对象
代表的是类。
准备: 静态成员开辟空间。
类的连接 : 验证 准备 解析
2.类加载机制: 双亲委派机制 父类加载
加载到方法区中的类需要保证唯一性,采用双亲委派,父类加载的机制。 1.启动/引导类加载器 2.扩展类加载器 3.应用程序/系统程序类加载器
反射创建对象
概述
1.Jvm中通过Class对象来创建该对象代表的类的对象
2.常用方法:
① newInstance() 调用空参的构造方法创建对象
② getConstructors() 获取所有的构造方法
③ getConstructor(Class<?>... parameterTypes)
3.Constructor:表示构造方法类
① newInstance(Object... initargs) 创建对象
代码
package com.demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
1.Jvm中通过Class对象来创建该对象代表的类的对象
2.常用方法:
① newInstance() 调用空参的构造方法创建对象
② getConstructors() 获取所有的构造方法
③ getConstructor(Class<?>... parameterTypes)
3.Constructor:表示构造方法类
① newInstance(Object... initargs) 创建对象
*/
public class Class类对象的常用方法 {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
// A a = new A();
/* Class clazz = Class.forName("com.demo.A");
A a = (A) clazz.newInstance();
a.show();
Class clazz1 = B.class;
B b = (B) clazz1.newInstance();
System.out.println(b);*/
// ② getConstructors() 获取所有的构造方法
Class clazz2 = A.class;
/* Constructor[] cs = clazz2.getConstructors();
for (Constructor c : cs) {
System.out.println(c);
}*/
Constructor cn = clazz2.getConstructor(String.class, int.class);
// A a1 = new A("张三",19);
A o = (A) cn.newInstance("张三", 19);
// System.out.println(cn);
o.show();
}
}
class A{
String name;
int age;
public void show(){
System.out.println(name +":"+age);
}
public A() {
}
public A(String name, int age) {
this.name = name;
this.age = age;
}
}
class B {}
package com.demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
1.getConstructors()细节问题:
注意:凡是只有getXXX的形式,都只能获取public修饰的。如果需要获取
其它的权限的时候,使用getDeclaredXXX()
2.关于private访问权限的取消:
setAccessible(boolean flag) 如果参数为true 表示取消java的语法访问检测,称为打开权限。
*/
public class Class类创建对象 {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class clazz = Person.class;
/*Constructor[] cs = clazz.getDeclaredConstructors();
for (Constructor c : cs) {
System.out.println(c);
}*/
Constructor c = clazz.getDeclaredConstructor(String.class, int.class);
//打开权限
c.setAccessible(true);
Person p = (Person) c.newInstance("张三", 19);
p.show();
}
}
class Person{
String name;
int age;
public void show(){
System.out.println(name +":"+ age);
}
public Person() {
}
private Person(String name, int age) {
this.name = name;
this.age = age;
}
}
反射构造方法的细节问题
概述
1.getConstructors()细节问题:
注意:凡是只有getXXX的形式,都只能获取public修饰的。如果需要获取
其它的权限的时候,使用getDeclaredXXX(),该形式只能用于本类声明,但是getXXX的形式,如果
父类是public也可以获取。
2.关于private访问权限的取消:
setAccessible(boolean flag) 如果参数为true 表示取消java的语法访问检测,称为打开权限。
代码
package com.demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
1.getConstructors()细节问题:
注意:凡是只有getXXX的形式,都只能获取public修饰的。如果需要获取
其它的权限的时候,使用getDeclaredXXX()
2.关于private访问权限的取消:
setAccessible(boolean flag) 如果参数为true 表示取消java的语法访问检测,称为打开权限。
*/
public class Class类创建对象 {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class clazz = Person.class;
/*Constructor[] cs = clazz.getDeclaredConstructors();
for (Constructor c : cs) {
System.out.println(c);
}*/
Constructor c = clazz.getDeclaredConstructor(String.class, int.class);
//打开权限
c.setAccessible(true);
Person p = (Person) c.newInstance("张三", 19);
p.show();
}
}
class Person{
String name;
int age;
public void show(){
System.out.println(name +":"+ age);
}
public Person() {
}
private Person(String name, int age) {
this.name = name;
this.age = age;
}
}
反射获取属性(字段field)
概述
1.获取字段:
① getField(String name) 指定的修饰符为public字段
② getFields() 修饰符为public所有字段
③ getDeclaredField(String name) 指定的声明的字段
④ getDeclaredFields() 指定的声明所有的字段
2.设置/获取字段值 setter getter
① set(Object obj, Object value) /get(Object obj)
代码
package com.demo;
import java.lang.reflect.Field;
/**
1.获取字段:
① getField(String name) 指定的修饰符为public字段
② getFields() 修饰符为public所有字段
③ getDeclaredField(String name) 指定的声明的字段
④ getDeclaredFields() 指定的声明所有的字段
2.设置/获取字段值 setter getter
① set(Object obj, Object value) /get(Object obj)
*/
public class 字段 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InstantiationException {
Class clazz = Student.class;
Field age = clazz.getField("age");
/*System.out.println(age);
Class clazz1 = MiddleStudent.class;
Field age1 = clazz1.getField("age");
System.out.println(age1);*/
Student st = (Student) clazz.newInstance();
/*age.set(st, 20);
System.out.println(age.get(st));*/
Field name = clazz.getDeclaredField("name");
//打开权限
name.setAccessible(true);
name.set(st, "张三");
st.show();
}
}
class Student{
private String name;
public int age;
public void show(){
System.out.println(name +":"+ age);
}
public Student() {
}
private Student(String name, int age) {
this.name = name;
this.age = age;
}
}
class MiddleStudent extends Student{}
反射之方法
概念
1.获取方法:
① getMethod(String name, Class<?>... parameterTypes)
② getMethods()
③ getDeclaredMethod(String name, Class<?>... parameterTypes)
④ getDeclaredMethods()
2.调用方法:
invoke(Object obj, Object... args)
① 第一个参数表示对象,如果是静态方法可以置为null
② 第二个参数表示方法的实参,如果没有参数也可以置为null或不写。
③ 该方法的返回值为方法调用的返回值。
void 返回值为null
代码
package com.demo;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
1.获取方法:
① getMethod(String name, Class<?>... parameterTypes)
② getMethods()
③ getDeclaredMethod(String name, Class<?>... parameterTypes)
④ getDeclaredMethods()
2.调用方法:
invoke(Object obj, Object... args)
① 第一个参数表示对象,如果是静态方法可以置为null
② 第二个参数表示方法的实参,如果没有参数也可以置为null或不写。
③ 该方法的返回值为方法调用的返回值。
void 返回值为null
*/
public class 方法 {
public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//先找到Class
Class clazz = Worker.class;
//创建Worker类的对象
Worker wr = (Worker) clazz.newInstance();
//获取show方法 由于该方法没有参数,可以使用null或直接省略不写。
/*Method show = clazz.getMethod("show");
Object value = show.invoke(wr);
System.out.println(value);*/
/*Method working = clazz.getMethod("working", String.class);
Object value1 = working.invoke(wr, "建筑");
System.out.println(value1);*/
Method add = clazz.getMethod("add", int.class, int.class);
int value2 = (int) add.invoke(wr, 15, 23);
System.out.println(value2);
Method fun = clazz.getMethod("fun" );
Object value3 = fun.invoke(null);
}
}
class Worker{
String name;
int age;
public void show(){
System.out.println(name +":"+ age);
}
public void working(String action){
System.out.println("工人从事"+action+"行业");
}
public int add(int a,int b){
return a+b;
}
public static void fun(){
System.out.println("aaaaa");
}
}
反射总结
概述
概念 Class 获取方式三种 字段 set/get 构造方法 newInstance 方法 invoke
反射的其它方法
package com.demo;
/**
1.getInterfaces() 获取父接口
2.getName() 返回类/接口的完全限定名。
3.getSuperclass()获取父类
4.getClassLoader() 获取类加载器
*/
public class 反射的其它方法 {
public static void main(String[] args) {
Class clazz = ZiA.class;
/*Class[] in = clazz.getInterfaces();
for (Class aClass : in) {
System.out.println(aClass.getName());
}*/
/*Class sc = clazz.getSuperclass();
System.out.println(sc);*/
ClassLoader cl = clazz.getClassLoader();
System.out.println(cl.getParent().getParent());
}
}
class A {
}
interface T{}
class ZiA extends A implements T{}
暴力反射
package com.exec;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class 暴力反射 {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
Class clazz = list.getClass();
Method add = clazz.getMethod("add", Object.class);
add.invoke(list, "abc");
System.out.println(list);
}
}
来电显示
package com.exec;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
/**
1.手机的来电显示:
2.配置文件。xml
*/
public class 来电显示 {
public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
Properties prp = new Properties();
prp.load(new FileReader(new File("day27b\\p.properties")));
Class clazz = Class.forName(prp.getProperty("className"));
PhoneI pi = (PhoneI) clazz.newInstance();
pi.display();
}
}
class PhoneI{
public void display(){
System.out.println("显示号码");
}
}
class PhoneII extends PhoneI{
@Override
public void display() {
super.display();
System.out.println("大头贴");
}
}
class PhoneIII extends PhoneII{
@Override
public void display() {
super.display();
System.out.println("归属地。。。");
}
}
class PhoneIIII extends PhoneIII{}