-----------android培训、java培训、java学习型技术博客、期待与您交流!------------
一、获取Class对象的三种方式:
1.调用Object类的getClass():任何类都会继承此方法;
2.任何的数据类型(包括基本类型)都有一个:静态的class属性:
Student.class;
int.class
3.调用Class类的静态方法forName(String 全名限定的类名):(常用)
通过这个Class对象,可以获取Student类内部的成员属性、构造方法、成员方法的一些信息,并能够调用它们;
package cn.hebei.sjz_反射;
/*
* 获取Class对象的三种方式:
*/
public class Demo {
public static void main(String[] args) throws Exception {
Student stu = new Student();
Class stuClass1 = stu.getClass();
Class stuClass2 = Student.class;
Class stuClass3 = Class.forName("cn.itcast.demo01_获取Class对象的三种方式.Student");
System.out.println(stuClass1 == stuClass2);
System.out.println(stuClass1 == stuClass3);
Student stu2 = new Student();
Class stuClass4 = stu2.getClass();
System.out.println(stuClass1 == stuClass4);
}
}
Class类:
批量的:
Constructor[] getConstructors() :获取所有的"公有构造方法"
Constructor[] getDeclaredConstructors() :获取全部(包括私有)的构造方法;
获取某个构造方法
Constructor getConstructor(Class ... parameterTypes) :获取指定的"公有构造方法";
Constructor getDeclaredConstructor(Class ... parameterTypes) :获取指定的构造方法(包括私有的);
调用某个构造方法:
Constructor的 Object newInstance(Object... initargs) :调用指定构造方法,并实例化此类的对象;
暴力访问:如果私有成员,需要设置暴力访问;
Constructor的setAccessible(true):不进行权限检查;
package cn.hebei.sjz_通过Class对象获取构造方法并调用;
import java.lang.reflect.Constructor;
public class Demo {
public static void main(String[] args) throws Exception {
//1.获取Student的Class对象
Class stuClass = Class.forName("cn.itcast.demo02_通过Class对象获取构造方法并调用.Student");
System.out.println("************获取所有的\"公有构造方法\"*******************");
Constructor[] conArray = stuClass.getConstructors();
for(Constructor c : conArray){
System.out.println(c);
}
System.out.println("************获取所有的构造方法(包括私有的)***************");
conArray = stuClass.getDeclaredConstructors();
for(Constructor c : conArray){
System.out.println(c);
}
System.out.println("************获取\"公有构造方法\"***********************");
Constructor con = stuClass.getConstructor(String.class);//获取的是"具有String类型形参的"公有构造方法
//Constructor con = stuClass.getConstructor(String.class,int.class);
Object obj = con.newInstance("刘德华");//调用此构造方法,并传递实参:相当于:Object obj = new Student("刘德华");
System.out.println("************获取\"私有构造方法\"并调用*******************");
con = stuClass.getDeclaredConstructor();
//设置暴力访问
con.setAccessible(true);
obj = con.newInstance();
}
}
Class类的方法:
批量的:
Field[] getFields():获取所有"公有属性";
Field[] getDeclaredFields() :获取所有成员属性(包括私有):
获取单个成员属性
Field getField(String name) :获取指定的"公有属性";
Field getDeclaredField(String name) :获取指定的属性,包括私有的;
为成员属性赋值:(注意:1.一定要先实例化此类对象;2.访问私有属性前,要设置暴力访问)
Field的 void set(Object obj, Object value)
package cn.hebei.sjz_通过Class对象获取成员属性;
import java.lang.reflect.Field;
public class Demo {
public static void main(String[] args) throws Exception {
// 1.获取Student的Class对象
Class stuClass = Class.forName("cn.itcast.demo03_通过Class对象获取成员属性并调用.Student");
System.out.println("********************获取所有\"公有属性\"************************");
Field[] fieldArray = stuClass.getFields();
for (Field f : fieldArray) {
System.out.println(f);
}
System.out.println("********************获取所有属性(包括私有的)************************");
fieldArray = stuClass.getDeclaredFields();
for (Field f : fieldArray) {
System.out.println(f);
}
// 创建一个Student对象
Object obj = stuClass.getConstructor().newInstance();
System.out.println("*********************获取公有属性,并调用*********************************");
Field f = stuClass.getField("name");
System.out.println("赋值前打印:" + obj);
f.set(obj, "刘德华");
System.out.println("赋值后打印:" + obj);
System.out.println("*********************获取私有属性,并赋值*********************************");
f = stuClass.getDeclaredField("score");
// 暴力访问
f.setAccessible(true);
f.set(obj, 88.5);
System.out.println(obj);
}
}
Class类的方法:
批量的:
Method[] getMethods():获取所有"公有方法"(包括继承的)
Method[] getDeclaredMethods() :获取所有成员方法(包括私有):
获取单个成员方法
Method getMethod(String name, Class... parameterTypes) :获取指定的"公有方法";
Method getDeclaredMethod(String name, Class... parameterTypes) :获取指定的方法,包括私有的;
调用方法:(注意:1.要先创建此类的对象;2.调用私有方法前,要先设置暴力访问)
Method:
Object invoke(Object obj, Object... args) :调用Method所代表的方法:
返回值:此Method对象调用所代表的方法,所获取的返回值;
形参:obj:方法所属对象;
args:Method所代表的那个方法的实参列表;
package cn.hebei.sjz_通过Class对象获取成员方法并调用;
import java.lang.reflect.Method;
public class Demo {
public static void main(String[] args) throws Exception {
//1.获取Class对象
Class stuClass = Class.forName("cn.itcast.demo04_通过Class对象获取成员方法并调用.Student");
System.out.println("*************获取所有\"公有方法\"*******************");
Method[] methodArray = stuClass.getMethods();
for(Method m : methodArray){
System.out.println(m);
}
System.out.println("**************获取所有的方法(包括私有的)***************");
methodArray = stuClass.getDeclaredMethods();
for(Method m : methodArray){
System.out.println(m);
}
//创建Student对象
Object obj = stuClass.getConstructor().newInstance();
System.out.println("**************获取公有的,带参的show1()方法,并调用******");
Method m = stuClass.getMethod("show1", String.class,int.class);
Object result = m.invoke(obj, "刘德华",20);//调用show1()方法
System.out.println("调用的返回值:" + result);
System.out.println("***************获取私有的,无参的、无返回值的show4()方法,并调用****************");
m = stuClass.getDeclaredMethod("show4");
m.setAccessible(true);
m.invoke(obj);
}
}
练习1
package cn.hebei.sjz_通过反射运行配置文件内容;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Properties;
/*
* 通过反射运行配置文件内容
*/
public class Demo {
public static void main(String[] args) throws Exception {
//1.获取Student的Class对象
//Class stuClass = Class.forName("cn.hebei.sjz_通过反射运行配置文件内容.Student");
String classPath = getValue("className");
Class stuClass = Class.forName(classPath);
//2.实例化一个Student对象
Object obj = stuClass.getConstructor().newInstance();
//3.调用方法
//Method m = stuClass.getMethod("show");
Method m = stuClass.getMethod(getValue("methodName"));
m.invoke(obj);
}
//一个方法,获取配置文件中的某个键对应的值
public static String getValue(String key) throws IOException{
Properties pro = new Properties();
FileReader in = new FileReader("properties.ini");
pro.load(in);
in.close();
return pro.getProperty(key);
}
}
练习2:
package cn.hebei.sjz_通过反射越过泛型检查;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/*
*
* 通过反射越过泛型检查:
*
* 1.定义一个具有String泛型的集合,要求成功向集合中添加一个int数据;
*/
public class Demo {
public static void main(String[] args) throws Exception, SecurityException {
List<String> strList = new ArrayList<>();
strList.add("aaa");
strList.add("bbb");
//strList.add(10);
//通过反射
Class listClass = strList.getClass();
//获取add方法
Method addMethod = listClass.getMethod("add", Object.class);
//调用add方法
addMethod.invoke(strList, 10);
//遍历集合
for(Object o : strList){
System.out.println(o);
}
}
}
package cn.hebei.sjz_通用方法;
import java.lang.reflect.Field;
/*
* 通用方法
*/
public class Demo {
public static void main(String[] args) throws SecurityException, Exception {
Cat c = new Cat();
setValue(c, "name", "波斯猫");
c.show();
}
// 通过反射写一个通用的设置某个对象的某个属性为指定的值
public static void setValue(Object target, String fieldName, Object value)
throws Exception, SecurityException {
// 1.获取Class对象
Class aClass = target.getClass();
// 2.获取字段
Field f = aClass.getDeclaredField(fieldName);
// 3.暴力访问
f.setAccessible(true);
// 4.设置
f.set(target, value);
}
}
代理类的目的:是为所代理的类的某些方法,增加一些额外的操作;
Java中实现动态代理:
步骤:
1.自定义类,实现InvocationHandler接口;
重写invoke()方法:需要代理的方法,都要经过此方法,
我们可以在此方法中做我们想要做的事情;
2.动态生成代理对象:
Proxy类静态方法:newProxyInstance()
注意:Java的动态代理机制是基于"接口"的,也就是所有需要被代理的类都必须实现某个接口,以达到它们作为共同类型的目的;