**反射机制的作用:**通过反射机制来访问class文件的java对象的属性,方法,构造方法等
获取字节码文件常用的三种方法:
第一种:Class c1 = Class.forName(“java.lang.String”);
完整包名+类名 静态方法方法参数是一个字符串字符串需要时一个完成的类名 完整的类名必须带有包名
第二种:Class c2 = 对象.getClass();
第三种方式 java中任何一种类型,都有相对应的class属性。Class z = String.class; Class m = Date.class;Class e = int .class;
如何获取类的绝对路径?在任何系统上都是通用路径,前提文件时在src根目录下
String path = Thread.currentThread().getContextClassLoader()
.getResource("classinfo.properties").getPath();
获取了Class文件我们能做什么?
1.通过Class的newInstance()实例化对象,并且调用了无参构造方法
2.Class. forName()方法执行,进行了类加载,静态代码块执行
3.通过io流读取classinfo.properties文件,或许key和value,然后通过反射机制,实例化对象进行。
classinfo.properties文件
className=Reflect.User
public class ReflcetTest03 {
public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
//通过io流读取classinfo.properties文件
FileReader reader = new FileReader("D:\\JDEA\\untitled1\\src\\classinfo.properties");
//创建属性类对象 key value 都是String类型的
Properties pro = new Properties();
//加载
pro.load(reader);
//关闭流
reader.close();
//通过key获取value
String className = pro.getProperty("className");
//通过反射机制实例化对象,实例化的是Usr类
Class c = Class.forName(className);
Object obj = c.newInstance();
System.out.println(obj);
}
}
class User{
public User() {
System.out.println("无参构造执行");
}
}
获取字段/属性的类型int,String,double等/修饰符列public static final/名字
public static void main(String[] args) throws Exception {
//获取整个类
Class studentClass = Class.forName("Reflect.Student");
String s1 = studentClass.getName();//返回完整类名
System.out.println(s1);
String s2 = studentClass.getSimpleName();//返回简单类名
System.out.println(s2);
//获取类中所有Filed方法,但是只能获取public修饰的
Field[] fields = studentClass.getFields();
System.out.println(fields.length);//测试数组中只有一个元素
//取出这个数组中Field字段/属性
Field f = fields[0];
//取出Field的名字
String s = f.getName();
System.out.println(s);
System.out.println("-------------");
//获取所有的Field
Field[] field = studentClass.getDeclaredFields();
System.out.println(field.length);//数组中有4个元素
for (Field ff : field){
//获取属性修饰符列表
//修饰符可能有多个 public static final ff.getModifiers();
int i = ff.getModifiers();
//返回值是数字,将数字转换成字符串
String modifier = Modifier.toString(i);
System.out.println(modifier);
//获取属性类型
//变量.获取类型.获取类型的名字
String fName = ff.getType().getName();//也可以获取简单名字
System.out.println(fName);
//获取属性名字
System.out.println(ff.getName());
}
}
}
//反射属性
class Student{
//Field翻译为字段, 其实就是属性/成员
//4个Field分别采用了不同的访问控制权限修饰符
public int no ;//整个是一个Field对象
private String name;
protected int age;
boolean sex;
public static final double PI = 3.1415;
public Student() {
}
public Student(int no, String name, int age, boolean sex) {
this.no = no;
this.name = name;
this.age = age;
this.sex = sex;
}
}
反射Method方法
public class ReflcetTest11 {
public static void main(String[] args) throws ClassNotFoundException {
//获取类
Class user = Class.forName("Reflect.UserService");
//获取所有Method(包括私有)
Method[] methods = user.getDeclaredMethods();
//System.out.println(methods.length);//2
//遍历Method
for (Method method : methods){
//获取修饰符列表
System.out.println(Modifier.toString(method.getModifiers()));
//或许返回值类型
System.out.println(method.getReturnType().getSimpleName());
//获取方法名
System.out.println(method.getName());
//方法的修饰符列表(一个方法的参数可能会有多个)需要遍历
Class[] ParameterTypes = method.getParameterTypes();
for (Class ParameterType : ParameterTypes){
System.out.println(ParameterType.getSimpleName());
}
}
}
}
/*
*功能描述
* @author 肥蛋
* @date
* @param name 用户名
* @param password 密码
* @return true表示成功 false表示失败
*/
class UserService{
public boolean login(String name,String password){
if ("admin".equals(name) && "123".equals(password)){
return true;
}return false;
}
public void logout(){
System.out.println("系统安全退出");
}
}
总结:想获取类里的什么就获取类然后调用getDeclared-----相应的构造方法
getDeclaredConstructors();获取构造方法,返回Constructor数组
getDeclaredMethods();获取方法,返回Method数组
getDeclaredFields();获取字段/属性,返回Field数组
怎么利用反射机制调用构造方法?
public class ReflectTest15 {
public static void main(String[] args) throws Exception {
Class Vip = Class.forName("Reflect.Vip");
//调用无参数构造方法
Object obj = Vip.newInstance();
//获取构造方法
Constructor c1 = Vip.getDeclaredConstructor(int.class,String.class,String.class,boolean.class);
Constructor c2 = Vip.getDeclaredConstructor(int.class,String.class);
//调用构造方法
Object c1Obj = c1.newInstance(111,"java","1990",true);
System.out.println(c1Obj);
Object c2Obj = c2.newInstance(111,"java");
System.out.println(c2Obj);
}
class Vip{
int no;
String name;
String birth;
boolean sex;
public Vip() {
}
public Vip(int no) {
this.no = no;
}
public Vip(int no, String name) {
this.no = no;
this.name = name;
}
public Vip(int no, String name, String birth) {
this.no = no;
this.name = name;
this.birth = birth;
}
public Vip(int no, String name, String birth, boolean sex) {
this.no = no;
this.name = name;
this.birth = birth;
this.sex = sex;
}
@Override
public String toString() {
return "Vip{" +
"no=" + no +
", name='" + name + '\'' +
", birth='" + birth + '\'' +
", sex=" + sex +
'}';
}
}
}
怎么通过反射机制调用方法?
public class ReflectTest13 {
public static void main(String[] args) throws Exception {
Class UserService = Class.forName("Reflect.UserService");
//创建对象,调用无参数构造方法
Object obj = UserService.newInstance();
Method loginMethod = UserService.getDeclaredMethod("login", String.class,String.class);
//loginMethod是方法 obj是对象 "admin","123"是传入参数 retValue是返回值
Object retValue = loginMethod.invoke(obj, "admin","123");
System.out.println(retValue);
}
}
class UserService{
public boolean login(String name,String password){
if ("admin".equals(name) && "123".equals(password)){
return true;
}return false;
}
public void logout(){
System.out.println("系统安全退出");
}
}
怎么通过反射机制访问一个java属性?
给属性赋值set
获取属性值get
public static void main(String[] args) throws Exception{
//使用反射机制,给对象赋值
Class stuClass = Class.forName("Reflect.Student");
//调用无参数构造方法,获取对象obj
Object obj = stuClass.newInstance();
//获取no属性(根据属性名称来获取Field)
Field nofield = stuClass.getDeclaredField("no");
//赋值set 取值get
nofield.set(obj, 111);
System.out.println(nofield.get(obj));
//可以访问私有变量嘛?
Field nameFiled = stuClass.getDeclaredField("name");
//打破封装(缺点:安全性太差)
//这样设置之后外部也是可以访问private的
nameFiled.setAccessible(true);
//给name属性赋值
nameFiled.set(obj, "jack");
System.out.println(nameFiled.get(obj));
}
class Student{
//Field翻译为字段, 其实就是属性/成员
//4个Field分别采用了不同的访问控制权限修饰符
public int no ;//整个是一个Field对象
private String name;
protected int age;
boolean sex;
public static final double PI = 3.1415;
public Student() {
}
public Student(int no, String name, int age, boolean sex) {
this.no = no;
this.name = name;
this.age = age;
this.sex = sex;
}
}
怎么获取类实现接口和父类?
/*获取类实现接口和父类*/
public class ReflectTest16 {
public static void main(String[] args) throws ClassNotFoundException {
Class c = Class.forName("java.lang.String");
//类的父类
Class superclass = c.getSuperclass();
System.out.println(superclass);
//实现接口
Class[] interfaceClass = c.getInterfaces();
for (Class interfacer : interfaceClass){
System.out.println(interfacer.getName());
}
}
}
资源绑定器
便于获取配置文件中的内容。使用以下这个方式的时候,属性配置文件xxx.properties必须放刀类路径下。、
文件内容className=Reflect.User
public class ResourceBundleTest01 {
public static void main(String[] args) {
//资源绑定器,只能绑定xxx.properties,并且文件在类路径下。文件扩展名只能是properties
//并且在写路径的时候,路径后边的扩展名不能写
ResourceBundle bundle = ResourceBundle.getBundle("classinfo");
String className = bundle.getString("className");
System.out.println(className);
}
}