反射:框架设计的灵魂
反射:将类的各个组成部分封装为其他对象,这就是反射机制
优点:
1.可以在程序运行过程中,操作这些对象
2.可以解耦,提高程序的可扩展性.后期学习的ssh框架都会用来
一、字节码对象Class的功能:
1.获取成员变量:
1. Field[] getFields() :获取所有public修饰的成员变量
2. Field getField(String name) 获取指定名称(单个)的 public修饰的成员变量
3. Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符(private)
4. Field getDeclaredField(String name) 获取指定名称的成员变量,不考虑修饰符(private)
2.获取构造方法:
1. Constructor<?>[] getConstructors()
2. Constructor<T> getConstructor(类<?>... parameterTypes)
3. Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
4. Constructor<?>[] getDeclaredConstructors()
3.获取成员方法:
1. Method[] getMethods()
2. Method getMethod(String name, 类<?>... parameterTypes)
3. Method[] getDeclaredMethods()
4. Method getDeclaredMethod(String name, 类<?>... parameterTypes)
二、获取字节码对象Class的三种方式:
1.Class.forName(“全类名”):
public class Dog {
public String name;
int age;
protected String color;
private String eat;
public Dog() {
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
", eat='" + eat + '\'' +
'}';
}
}
=============================执行方法===================================
public class DogExample {
public static void main(String[] args) throws Exception {
Class<?> aClass = Class.forName("com.qst.opp.Dog");
Object obj = aClass.newInstance();
Field[] fields01 = aClass.getFields();
for (Field f:fields01) {
System.out.println("获取公开的所有属性信息:"+f);
}
Field name = aClass.getField("name");
System.out.println(name);
Field[] fields02 = aClass.getDeclaredFields();
for (Field f:fields02) {
System.out.println("获取所有的属性信息:"+f);
}
System.out.println("===============================");
Field age = aClass.getDeclaredField("age");
Field eat = aClass.getDeclaredField("eat");
System.out.println(age);
System.out.println(eat);
System.out.println("===============================");
name.set(obj,"大黄");
System.out.println("查看赋值操作:"+obj);
Object o = name.get(obj);
System.out.println("通过反射取值:"+o);
}
}
2.类名.class:
public class Cat {
public Cat() {
}
public void eat(){
System.out.println("猫吃鱼");
}
void run(){
System.out.println("跑");
}
protected String sleep(){
return "猫爱睡觉";
}
private String ww(){
return "ww";
}
}
===============================执行方法===============================
public class CatExample {
public static void main(String[] args) throws Exception {
Class<Cat> aClass = Cat.class;
Cat cat = (Cat)aClass.newInstance();
Method[] methods01 = aClass.getMethods();
for (Method m:methods01) {
System.out.println("读取公开的方法:"+m);
}
Method eat = aClass.getMethod("eat");
Method[] methods02 = aClass.getDeclaredMethods();
for (Method m:methods02) {
System.out.println("读取所有的方法:"+m);
}
System.out.println("=============================");
Method run = aClass.getDeclaredMethod("run");
Method sleep = aClass.getDeclaredMethod("sleep");
Method ww = aClass.getDeclaredMethod("ww");
System.out.println("读取不公开的方法:"+run);
System.out.println("读取不公开的方法:"+sleep);
System.out.println("读取不公开的方法:"+ww);
System.out.println("==============测试方法执行===============");
Object invoke = eat.invoke(cat);
System.out.println("测试无返回值,公开的:"+invoke);
Object invoke1 = sleep.invoke(cat);
System.out.println("测试有返回值,且不公开:"+invoke1);
ww.setAccessible(true);
Object invoke2 = ww.invoke(cat);
System.out.println("测试有返回值,且不公开:"+invoke2);
}
}
3.对象.getClass():
public class Apple {
private String color;
public int price;
public Apple() {
}
private Apple(String color) {
this.color = color;
}
private Apple(int price) {
this.price = price;
}
public Apple(String color, int price) {
this.color = color;
this.price = price;
}
@Override
public String toString() {
return "Apple{" +
"color='" + color + '\'' +
", price=" + price +
'}';
}
}
============================执行方法=================================
public class AppleExample {
public static void main(String[] args) throws Exception {
Apple apple = new Apple();
Class<? extends Apple> aClass = apple.getClass();
Constructor<?>[] constructors = aClass.getConstructors();
for (Constructor cr:constructors) {
System.out.println("获取公开的构造:"+cr);
}
Constructor<?>[] constructors1 = aClass.getDeclaredConstructors();
for (Constructor cr:constructors1) {
System.out.println("获取所有的构造:"+cr);
}
System.out.println("==========================");
Constructor<?> constructor0 = aClass.getConstructor();
Constructor<?> constructor1 = aClass.getConstructor(String.class,int.class);
Constructor<?> constructor3 = aClass.getDeclaredConstructor(int.class);
System.out.println(constructor3);
System.out.println("=============111=============");
Constructor<?> ctr = aClass.getConstructor();
Apple app = (Apple) ctr.newInstance();
System.out.println(app);
Constructor<?> ctr1 = aClass.getConstructor(String.class,int.class);
Apple app1 = (Apple) ctr1.newInstance("红富士",20);
System.out.println(app1);
System.out.println("==========================");
Constructor<?> cturs = aClass.getDeclaredConstructor(int.class);
cturs.setAccessible(true);
Apple ap01 = (Apple) cturs.newInstance(222);
System.out.println(ap01);
}
}
三、总结:
1.方法中只要带有后缀"s"的,就是获取所有的
2.方法中只要带有"Declared"的,就是可以获取私有(方法/成员变量/构造方法)
3.Class.forName("全类名"):将字节码文件加载进内存,返回Class对象;多用于配置文件,将类名定义在配置文件中。读取文件,加载类
4.类名.class:通过类名的属性class获取;多用于参数的传递
5.对象.getClass():getClass()方法在Object类中定义着。多用于对象的获取字节码的方式
总结:同⼀个字节码⽂件(*.class)在⼀次程序运⾏过程中,只会被加载⼀次,不论通过哪⼀种⽅式获取的Class对象
都是同⼀个
四、框架的配置文件–反射简单的实现
package com.soft;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ReflectExample {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("initClass.properties"));
byte[] buffer = new byte[1024];
int len = bis.read(buffer);
String content = new String(buffer, 0, len);
System.out.println(content);
String[] strs = content.split(":");
String className = strs[0];
String methodName = strs[1];
Class<?> aClass = Class.forName(className);
Object obj = Class.forName(className).newInstance();
Method method = aClass.getMethod(methodName);
Object invoke = method.invoke(obj);
System.out.println(invoke);
}
}
========================学生类=======================
package com.soft;
public class Student {
private String name;
private int age;
int age2;
public String address;
public String newAddress;
public int num;
public void study(){
System.out.println("学习");
}
public void superStudy(){
System.out.println("超级学习法");
}
public void miss() {
System.out.println("我好想你,xxx");
}
public Student() {
System.out.println("构造1");
}
public Student(String name, int age) {
System.out.println("构造2");
this.name = name;
this.age = age;
}
public Student( int age,String name) {
System.out.println("构造3");
this.name = name;
this.age = age;
}
public Student(String name, int age, int age2, String address) {
System.out.println("构造3");
this.name = name;
this.age = age;
this.age2 = age2;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("setName方法执行:"+name);
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getAge2() {
return age2;
}
public void setAge2(int age2) {
this.age2 = age2;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getNewAddress() {
return newAddress;
}
public void setNewAddress(String newAddress) {
this.newAddress = newAddress;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
}
=========================配置文件信息initClass.properties=============================
com.soft.Student:miss