目录
4.通过Class调用其他类中的构造函数 (也可以通过这种方式用Class创建其他类的对象)
8.取得其他类的全部属性,将这些整理在一起,也就是通过class取得一个类的全部框架
(2)想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,以完成代理的具体操作。
15.IoC原理-Spring中的IoC的实现原理=工厂模式+反射
1.通过一个对象获得完整的包名和类名
对象名.getClass().getName();
package com.review06.reflect;
public class Demo01 {
public static void main(String[] args) {
Demo01 demo01 = new Demo01();
System.out.println(demo01.getClass().getName());//打印结果:com.review06.reflect.Demo01
}
}
2.实例化Class类对象
package com.review06.reflect;
public class Demo02 {
public static void main(String[] args) {
Class<?> c1 = null;
Class<?> c2 = null;
Class<?> c3 = null;
try {
c1 = Class.forName("com.review06.reflect.Demo02"); //推荐
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
c2 = new Demo02().getClass();
c3 = Demo02.class;
System.out.println("类名称:"+c1.getName());
System.out.println("类名称:"+c2.getName());
System.out.println("类名称:"+c3.getName());
//运行结果:
//类名称:com.review06.reflect.Demo02
//类名称:com.review06.reflect.Demo02
//类名称:com.review06.reflect.Demo02
}
}
3.通过Class实例化其他类的对象
package com.review06.reflect;
class Person {
private String name;
private int age;
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;
}
@Override
public String toString() {
return "[" + this.name + " " + age +"]";
}
}
public class TestPerson {
public static void main(String[] args) {
Class<?> demo = null;
try {//idea的try/catch快捷键:先选中要try/catch的,然后Ctrl+Alt+t
demo = Class.forName("com.review06.reflect.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Person person = null;
try {
person = (Person)demo.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
person.setName("Green");
person.setAge(80);
System.out.println(person); //打印结果: [Green 80]
}
}
当我们把Person中的默认的无参构造函数取消的时候,自己定义只定义一个有参数的构造函数之后,会出现错误,比如定义如下的构造函数:
public Person(String name, int age) {
this.name = name;
this.age = age;
}
所以以后在编写使用Class实例化其他类的对象的时候,一定要自己定义无参的构造函数(防止无参构造函数被覆盖)。否则会出现以上错误!
4.通过Class调用其他类中的构造函数 (也可以通过这种方式用Class创建其他类的对象)
package com.review06.reflect;
import java.lang.reflect.Constructor;
class Men {
private String name;
private int age;
public Men() {
}
public Men(String name) {
this.name = name;
}
public Men(int age) {
this.age = age;
}
public Men(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "["+ this.name + " "+ this.age + "]";
}
}
class TestMen {
public static void main(String[] args) {
Class<?> demo = null;
try {
demo = Class.forName("com.review06.reflect.Men");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Men men1 = null;
Men men2 = null;
Men men3 = null;
Men men4 = null;
//取得全部的构造函数
Constructor<?> cons[] = demo.getConstructors();
try {
men1 = (Men) cons[0].newInstance();
men2 = (Men) cons[1].newInstance("Tom");
men3 = (Men) cons[2].newInstance(15);
men4 = (Men) cons[3].newInstance("Mike",62);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(men1+"\t"+men2+"\t"+men3+"\t"+men4);
}
}
5.返回一个类实现的接口
package com.review06.reflect;
interface Chinese {
public static final String name="Rollen";
public static int age = 20;
public void sayChinese();
public void sayHello(String name,int age);
}
interface A {}
class CPerson implements Chinese,A {
private String sex;
public CPerson() {
}
public CPerson(String sex) {
this.sex = sex;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public void sayChinese() {
System.out.println("hello,China");
}
@Override
public void sayHello(String name, int age) {
System.out.println(name +" "+ age);
}
}
public class TestChinese {
public static void main(String[] args) {
Class<?> demo = null;
try {
demo = Class.forName("com.review06.reflect.CPerson");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//保存所有的接口
Class<?> intes[] = demo.getInterfaces();
for(int i=0; i<intes.length; i++) {
System.out.println("实现的接口:"+intes[i].getName());//打印结果:实现的接口:com.review06.reflect.Chinese
}
//打印结果:
//实现的接口:com.review06.reflect.Chinese
//实现的接口:com.review06.reflect.A
}
}
(下面例子中,上面写过的Person类、Men类、CPerson类都省略不写了)
6.取得其他类中的父类
package com.review06.reflect;
public class TestSuper {
public static void main(String[] args) {
Class<?> demo = null;
try {
demo = Class.forName("com.review06.reflect.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//取得父类
Class<?> temp = demo.getSuperclass();
System.out.println("继承的父类为:"+temp.getName());
//打印结果: 继承的父类为:java.lang.Object
}
}
7.获得其他类中的全部构造函数
package com.review06.reflect;
import java.lang.reflect.Constructor;
public class TestConstructor {
public static void main(String[] args) {
Class<?> demo = null;
try {
demo = Class.forName("com.review06.reflect.Men");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Constructor<?> cons[] = demo.getConstructors();
for(int i=0; i<cons.length; i++) {
System.out.println("构造方法:"+cons[i]);
}
}
}
打印结果:
8.取得其他类的全部属性,将这些整理在一起,也就是通过class取得一个类的全部框架
package com.review06.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class TestAttribute {
public static void main(String[] args) {
Class<?> demo = null;
try {
demo = Class.forName("com.review06.reflect.CPerson");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("=======本类属性=======");
Field[] field = demo.getDeclaredFields();
for(int i=0; i<field.length; i++) {
//权限修饰符
int modifier = field[i].getModifiers();
String priv = Modifier.toString(modifier);
//属性类型
Class<?> type = field[i].getType();
System.out.println(priv+" "+type.getName()+" "+field[i].getName()+";");
}
System.out.println("\n=======实现的接口或者父类的属性=======");
//取得实现的接口或者父类的属性
Field[] field1 = demo.getFields();
for (int j=0; j<field1.length; j++) {
//权限修饰符
int modifier = field1[j].getModifiers();
String priv = Modifier.toString(modifier);
//属性类型
Class<?> type = field1[j].getType();
System.out.println(priv+" "+type.getName()+" "+field1[j].getName()+";");
}
}
}
9.通过反射调用其他类中的方法
package com.review06.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestMethod1 {
public static void main(String[] args) {
Class<?> demo = null;
try {
demo = Class.forName("com.review06.reflect.CPerson");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
//调用CPerson类中的sayChinese方法
Method method = demo.getMethod("sayChinese");
method.invoke(demo.newInstance());
//调用CPerson的sayHello方法
method = demo.getMethod("sayHello",String.class, int.class);
method.invoke(demo.newInstance(),"Tom",45);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
10.调用其他类的set和get方法
package com.review06.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class SetterGetter {
public static void main(String args[]) {
Class<?> demo = null;
Object obj = null;
try {
demo = Class.forName("com.review06.reflect.Person");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try {
obj = demo.newInstance();
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
e.printStackTrace();
}
setter(obj,"Name","张三", String.class);
getter(obj,"Name");
}
/**
* @param obj 操作的对象
* @param attr 操作的属性
*/
public static void getter(Object obj, String attr) {
try {
Method method = obj.getClass().getMethod("get"+attr);
System.out.println(method.invoke(obj));
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
/**
* @param obj 操作对象
* @param attr 操作的属性
* @param value 设置的值
* @param type 参数的值
*/
public static void setter(Object obj, String attr, Object value, Class<?> type) {
try {
Method method = obj.getClass().getMethod("set"+attr, type);
method.invoke(obj,value);
} catch (NoSuchMethodException e) {
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
11.通过反射操作属性
package com.review06.reflect;
import java.lang.reflect.Field;
public class TestSetAttr {
public static void main(String[] args) throws Exception {
Class<?> demo = null;
Object obj = null;
demo = Class.forName("com.review06.reflect.Person");
obj = demo.newInstance();
Field field = demo.getDeclaredField("name");
field.setAccessible(true);
field.set(obj,"李四");
System.out.println(field.get(obj));
}
}
12.通过反射取得并修改数组的信息
package com.review06.reflect;
import java.lang.reflect.Array;
public class TestAlertArrayInfo {
public static void main(String[] args) {
int[] temp = {1,5,7,45,4};
Class<?> demo = temp.getClass().getComponentType();
System.out.println("数组类型:"+ demo.getName());
System.out.println("数组长度:"+ Array.getLength(temp));
System.out.println("数组的第一个元素:"+Array.get(temp,0));
Array.set(temp,0,100);
System.out.println("修改后数组第一个元素为:"+Array.get(temp, 0));
}
}
13.通过反射修改数组大小
package com.review06.reflect;
import java.lang.reflect.Array;
public class TestAlertArraySize {
public static void main(String[] args) {
int[] temp = {1,2,4,5,1,3,15,13};
int[] newTemp = (int[]) arrayInc(temp,15);
print(newTemp);
System.out.println("\n===========");
String [] arr = {"a","b","c"};
String [] str1 = (String[])arrayInc(arr,8);
print(str1);
}
/**
* 修改数组大小
* @param obj 修改前的数组
* @param len 新数组长度
* @return 新的数组
*/
public static Object arrayInc(Object obj, int len) {
Class<?> arr = obj.getClass().getComponentType();
Object newArr = Array.newInstance(arr,len);
int co = Array.getLength(obj);
System.arraycopy(obj,0,newArr,0,co);
return newArr;
}
/**
* 打印
*/
public static void print(Object obj) {
Class<?> c = obj.getClass();
if(!c.isArray()) {
return;
}
System.out.println("数组长度为:"+Array.getLength(obj));
for(int i=0; i<Array.getLength(obj); i++) {
System.out.print(Array.get(obj,i) + " ");
}
}
}
14.动态代理
(1)获得类加载器
package com.review06.reflect;
public class GetClassLoader {
public static void main(String[] args) {
Person person = new Person();
System.out.println("Person的类加载器——"+
person.getClass().getClassLoader().getClass().getName());
//打印: Person的类加载器——sun.misc.Launcher$AppClassLoader
}
}
(2)想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,以完成代理的具体操作。
package com.review06.reflect;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicAgency {
public static void main(String[] args) {
MyInvocationHandler demo = new MyInvocationHandler();
Subject sub = (Subject) demo.bind(new RealSubject());
String info = sub.say("Chili",21);
System.out.println(info); //打印:Chili 21
}
}
//定义项目接口
interface Subject {
public String say(String name,int age);
}
//定义真实项目
class RealSubject implements Subject {
@Override
public String say(String name, int age) {
return name+" "+age;
}
}
class MyInvocationHandler implements InvocationHandler {
private Object obj = null;
public Object bind(Object obj) {
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),this::invoke);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object temp = method.invoke(this.obj,args);
return temp;
}
}
15.IoC原理-Spring中的IoC的实现原理=工厂模式+反射
(1)不用反射机制时的工厂模式例子:
package com.review06.reflect;
interface Phone {
public abstract void call();
}
class Huawei implements Phone {
@Override
public void call() {
System.out.println("Huawei");
}
}
class Mi implements Phone {
@Override
public void call() {
System.out.println("Mi");
}
}
//构造工厂类,以后在添加其他实例的时候只需要修改工厂类就OK了
class PhoneFactory {
public static Phone getInstance(String phoneName) {
Phone phone = null;
if("Huawei".equals(phoneName)) {
phone = new Huawei();
}
if("Mi".equals(phoneName)) {
phone = new Mi();
}
return phone;
}
}
public class TestFactory {
public static void main(String[] args) {
Phone phone = PhoneFactory.getInstance("Mi");
phone.call(); //打印:Mi
}
}
上述代码中,若再添加一个Phone的子类,就需要修改工厂类了。如果我们添加太多的子类,改的就会很多。
(2)利用反射机制的工厂模式
package com.review06.reflect;
import com.sun.xml.internal.ws.client.sei.ResponseBuilder;
interface RPhone {
public abstract void call();
}
class RHuawei implements RPhone {
@Override
public void call() {
System.out.println("Huawei");
}
}
class RMi implements RPhone {
@Override
public void call() {
System.out.println("Mi");
}
}
class RPhoneFactory {
public static RPhone getInstance(String ClassName) {
RPhone rphone = null;
try {
rphone = (RPhone) Class.forName(ClassName).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return rphone;
}
}
public class TestReflectFactory {
public static void main(String[] args) {
RPhone rphone = RPhoneFactory.getInstance("com.review06.reflect.RMi");
if(rphone != null) {
rphone.call();
}
}
}
现在就算我们添加任意多个子类的时候,工厂类就不需要修改。
使用反射机制的工厂模式可以通过反射取得接口的实例,但是需要传入完整的包和类名。而且用户也无法知道一个接口有多少个可以使用的子类,所以我们通过属性文件的形式配置所需要的子类。
(3)使用反射机制并结合属性文件的工厂模式(即IoC)
将上面的代码稍作修改(添加一个操作属性文件的类,修改main方法)
package com.review06.reflect;
import java.io.*;
import java.util.Properties;
interface RPhone {
public abstract void call();
}
class RHuawei implements RPhone {
@Override
public void call() {
System.out.println("Huawei");
}
}
class RMi implements RPhone {
@Override
public void call() {
System.out.println("Mi");
}
}
//操作属性文件类
class OperationPropFile {
public static Properties getPro() throws FileNotFoundException, IOException{
Properties pro = new Properties();
File file = new File("rphone.properties");
if(file.exists()) {
pro.load(new FileInputStream(file));
}else {
pro.setProperty("huawei","com.review06.reflect.RHuawei");
pro.setProperty("mi","com.review06.reflect.RMi");
pro.store(new FileOutputStream(file),"RPhone Class");
}
return pro;
}
}
class RPhoneFactory {
public static RPhone getInstance(String ClassName) {
RPhone rphone = null;
try {
rphone = (RPhone) Class.forName(ClassName).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return rphone;
}
}
public class TestReflectFactory {
public static void main(String[] args) throws FileNotFoundException,IOException {
Properties pro = OperationPropFile.getPro();
RPhone rphone = RPhoneFactory.getInstance(pro.getProperty("huawei"));
if(rphone != null) {
rphone.call(); //打印: Huawei
}
}
}