1.反射
1.1 什么是反射
反射是java语言中的一种机制,通过这种机制可以动态的实例化对象、读写属性、调用方法
根据提供给的字节码.class文件,拿到该类下面所有的属性和方法,调用
那么私有化的呢?反射最牛B的就是它还可以拿到该类中私有化的东西。
创建一个实体类,多点写属性和方法。
.java --> .class
通过.java得到.class ====编译
通过.class得到.java ====反编译(反射)
根据.class文件得到.java。
1.2 类类
所有狗 狗类 Dog 狗对象 旺财
所有猫 猫类 Cat 猫对象 肥波
所有类 类类 java.lang.Class 类对象 特定类
1.3 一切反射相关的代码都从获得类对象开始
获得类对象的三种方法 1. Class.forName(完整类名) 2. 类名.class 3. 对象.getClass()
1.2 案例
1.2.1 测试Bean
package test;
/**
* 学生测试类
*/
public class Student {
private String sid;
private String sname;
public Integer age;
public Student() {
super();
System.out.println("调用无参构造方法创建了一个学生对象");
}
public Student(String sid) {
super();
this.sid = sid;
System.out.println("调用带一个参数的构造方法创建了一个学生对象");
}
public Student(String sid, String sname) {
super();
this.sid = sid;
this.sname = sname;
System.out.println("调用带二个参数的构造方法创建了一个学生对象");
}
@SuppressWarnings("unused")
private Student(Integer age) {
System.out.println("调用Student类私有的构造方法创建一个学生对象");
this.age = age;
}
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public void hello() {
System.out.println("你好!我是" + this.sname);
}
public void hello(String name) {
System.out.println(name + "你好!我是" + this.sname);
}
@SuppressWarnings("unused")
private Integer add(Integer a, Integer b) {
return new Integer(a.intValue() + b.intValue());
}
}
1.2.2 测试反射方法
package com.test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import com.entity.Student;
import com.sun.jmx.mbeanserver.ModifiableClassLoaderRepository;
public class TestStudent {
public static void main(String[] args) {
try {
/*
* 动态获得类对象
*/
//==============第一种获得类对象的方法==========================================
//第一种获得类对象的方法,通过Class.forName(类路径)获得类对象--常用,可以通过改变path可以改变需要得到的类对象
String path = "com.entity.Student";
Class<?> c1 = Class.forName(path);
//===============第二种获得类对象的方法=========================================
//第二种获得类对象的方法,通过对象.class获得类对象
//Class c2 = Student.class;
//===============第三种获得类对象的方法=========================================
//第三种获得类对象的方法,通过实例化对象.getClass()获得类对象
//Class c3 = new Student().getClass();
//========================================================
/*
* 通过得到的类对象,获得动态对象,对属性进行读和写,进行调用方法
*/
//=============反射调用无参构造方法创建对象===========================================
/*
* 反射调用无参构造方法创建对象
*/
// //省略了一步//通过类对象,获得构造器
// Constructor con1 = c1.getConstructor();
// //通过无参构造器获得对象
// Student stu = (Student)con1.newInstance();
//=================反射调用有参构造方法创建对象 =======================================
/*
* 反射调用有参构造方法创建对象
*/
// //通过类对象获得构造器
// Constructor con = c1.getConstructor(String.class);
// //通过构造器实例化一个对象
// Student stu2 = (Student)con.newInstance("233");
//==================反射调用私有化的构造方法======================================
/*
* 反射调用私有化的构造方法
*/
//通过类对象获得公开构造器
// Constructor con2 = c1.getDeclaredConstructor(Integer.class);
// //将构造器设置为公开的
// con2.setAccessible(true);
// //然后就可以调用私有化的构造方法
// Student stu2 = (Student)con2.newInstance(123);
// System.out.println(stu2);
//========================================================
/*
* 通过反射得到对象的方法
*/
//通过反射得到动态对象
// Constructor con3 = c1.getConstructor();
// Student stu = (Student)con3.newInstance();
//====================通过反射得到对象的方法====================================
//通过类对象获得方法
// Method me1 = c1.getMethod("hello");
// //调用stu的方法(hello)
// me1.invoke(stu);
//=====================通过反射得到对象的私有化方法===================================
// Method me2 = c1.getDeclaredMethod("add", Integer.class,Integer.class);
// me2.setAccessible(true);
// System.out.println(me2.invoke(stu,10,20));
//========================================================
/*
*通过反射得到类对象对对象的属性进行读和写
*/
//通过类对象得到构造器
Constructor<?> con4 = c1.getConstructor();
//通过构造器得到无参的对象
Student stu4 = (Student)con4.newInstance();
//========================================================
//通过类对象,获得开放的属性
// Field sid = c1.getDeclaredField("sid");
// System.out.println(c1.getModifiers());
// //设置该属性为公开的
// sid.setAccessible(true);
// //设置属性stu4中的sid为“123”
// sid.set(stu4, "123");
// System.out.println(stu4);
//========================================================
// private static final String TEST = "name";
Field field = c1.getDeclaredField("TEST");
field.setAccessible(true);
//返回属性或方法的修饰符,返回的是int类型的
/*
* 1代表public
* 2代表private
* 8代表static
* 16代表final
*
*/
System.out.println(field.getModifiers());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
1.2.3 反射及基本使用方法
package com.test;
import com.entity.Student;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
/**
* 反射的测试类
* @author Administrator
*
*/
public class ReflectTest {
public static void main(String[] args) throws Exception {
Class<?> c = new Student().getClass(); //得到类对象
// String obj = c.getSimpleName(); //得到对象名
// Student newInstance = (Student)c.newInstance(); //动态实例化对象
// String cname = c.getName(); //得到完整类名(全路径名)
//-----------------获得某个属性----------------------------------------------
//得到所有公开的属性名以及属性类型,所在路径,返回所有公开的属性
Field[] field = c.getFields();
// for (Field field2 : field) {
// System.out.println(field2);
// }
//通过属性名获得类对象中的该属性的类型以及所在路径,返回当前属性,公开方法
Field field2 = c.getField("age");
// System.out.println(field2);
//返回所有属性,不受访问权限的限制
Field[] declaredFields = c.getDeclaredFields();
// for (Field field3 : declaredFields) {
// System.out.println(field3);
// }
//通过属性名获得类对象中的该属性的类型以及所在路径,返回当前属性,不受访问权限的限制
Field field4 = c.getDeclaredField("sid");
field4.setAccessible(true); //将属性的访问权限设置问公开的
Student stu =(Student)c.newInstance(); //实例化对象
field4.set(stu, "123"); //设置属性值
String str = (String) field4.get(stu); //获得属性值
// System.out.println(str);
// System.out.println(stu.getSid()+":sid"); //打印输出
//获得元素类型
Class<?> type = field2.getType();
// System.out.println(type);
//-----------------调用方法----------------------------------------------
//得到类对象的所有公开方法
Method[] methods = c.getMethods();
// for (Method method : methods) {
// System.out.println(method);
// }
//得到所有类对象的方法(不受访问修饰符的限制)
Method[] declaredMethods = c.getDeclaredMethods();
// for (Method method : declaredMethods) {
// System.out.println(method);
// }
//得到类对象的所有构造方法,不受访问修饰符的限制
Constructor<?>[] declaredConstructors = c.getDeclaredConstructors();
// for (Constructor<?> constructor : declaredConstructors) {
// System.out.println(constructor);
// }
//获得指定的公开方法
Method method = c.getMethod("hello",String.class,Integer.class);
//获得方法名0.
String methodName = method.getName();
//获得方法的返回类型
Class<?> returnType = method.getReturnType();
//返回该方法所有的参数类型,返回的是类对象
Class<?>[] parameterTypes = method.getParameterTypes();
// for (Class<?> class1 : parameterTypes) {
// System.out.println(class1+"--");
// }
//返回该方法所有的参数类型,返回的是数据类型
Parameter[] parameters = method.getParameters();
// for (Parameter parameter : parameters) {
// System.out.println(parameter);
// }
//调用方法
Method method2 = c.getMethod("hello",String.class,Integer.class);
// method2.invoke(stu,"za",123);
//-----------------对当前类对象的操作----------------------------------------------
//获得当前类对象所在的包路径
Package package1 = c.getPackage();
//返回当前类对象的父类
Class<?> superclass = c.getSuperclass();
//返回当前类对象的接口
Class<?>[] interfaces = c.getInterfaces();
// for (Class<?> class1 : interfaces) {
// System.out.println(class1);
// }
}
}
1.2.4 获得某个属性的方法
.getField(String) //返回某个公开的属性
.getFields() //返回所有公开的属性
.getDeclaredField(String)//返回某个私有属性
.getDeclaredField() //返回所有属性(任意访问权限)
.setAccessible(true) //为私有属性打开赋值权限
.set(object, value) //为某个属性赋值
.get(obj) //获得obj对象的某值
.getModifiers() //获得修饰符
.getType() //获得类型
.isStatic()
.isFinal()
……
.getMethods() //所有公开 的方法(含继承)
.getDeclaredMethods() //所有方法(含私有,但不包含继承)
.getReturnType() //获得方法的返回类型
.getParameterType() //获得方法的参数
.getDeclaredMethod(method-name, parameter)
.invoke(object, value) //调用方法及参数
.getDeclaredConstructors() //获得构造方法
.getParameterTypes() //构造方法参数类型
.getDeclaredConstructor(null) //获得不带参的构造方法
.getPackage() //获得当前类所在包
.getSuperclass() //获得父类的class
.getInterfaces() //获得接口
Modifier.isPublic(int)
1.2.5 反射的报错
1.java.lang.IllegalAccessException
原因:在类对象中没找对对于的方法或者访问权限受限
2.java.lang.NoSuchMethodException
原因:没有找到对于的方法,或者不存在