什么是类对象
-
反射:把Java类中的各种组成成分映射成单独的Java对象进行操作
-
类的对象:基于某个类new出来的对象,也称为实例对象
-
类对象:类加载的产物,封装了一个类的所有信息(类名、父类、接口、属性、方法、构造方法)
反射相关类
-
Class类:可以获取类和类的成员信息、
-
Field类:可以访问类的属性
-
Method类:可调用类的方法
-
Constructor类:可以调用类的构造方法
package com.fq.day24; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class ReflectDemo { public static void main(String[] args) throws Exception{ reflect5(); } //反射操作1:获取类对象 public static void reflect1()throws Exception{ //h获取类对象的三种方式 //1.创建类的对象 获取 Student s1 = new Student("小莲花",12); Class class1 = s1.getClass(); System.out.println(class1.hashCode()); //第二种方式:通过类名.class获取 Class class2 = Student.class; System.out.println(class2.hashCode()); //第三方式:通过Class.forName();推荐使用:耦合性低,编译时不依赖目标类 //Thread.currentThread().getContextClassLoader().getResource("").getPath() Class class3 = Class.forName("com.fq.day24.Student"); System.out.println(class3.hashCode()); } //反射操作2:获取类对象信息 public static void reflect2()throws Exception{ Class class1 = Class.forName("com.fq.day24.Student"); System.out.println("类的全名称:"+class1.getName()); //类的全名称:com.fq.day24.Student System.out.println("类的简单名称:"+class1.getSimpleName()); //类的简单名称:Student System.out.println("类的包名称:"+class1.getPackageName()); //类的包名称:com.fq.day24 System.out.println("类的父名:"+class1.getSuperclass().getName()); //类的父名:java.lang.Object Class[] interfaces = class1.getInterfaces(); //获取类实现的接口 for (Class inter:interfaces) { System.out.println(inter); //interface java.io.Serializable } } //反射操作3:获取类对象的基本信息 public static void reflect3()throws Exception{ Class class1 = Class.forName("com.fq.day24.Student"); //获取所有构造方法 Constructor[] constructors = class1.getConstructors(); for (Constructor s:constructors) { System.out.println(s); //public com.fq.day24.Student(java.lang.String,int) //public com.fq.day24.Student() } //获取单个构造方法,默认无参 Constructor con1 = class1.getConstructor(); Student s1 = new Student(); Student s2 = (Student) con1.newInstance(); System.out.println(s1.toString()); //Student{name='null', age=0} System.out.println(s2.toString()); //Student{name='null', age=0} //获取带参构造方法 Constructor constructor2 = class1.getConstructor(String.class,int.class); Student s3 = (Student) constructor2.newInstance("小莲花",22); System.out.println(s3.toString()); //Student{name='小莲花', age=22} //简写,调用无参构造 Student s4 = (Student) class1.newInstance(); System.out.println(s4.toString()); //Student{name='null', age=0} } //反射操作4:获取类对象的普通方法 public static void reflect4()throws Exception{ Class class1 = Class.forName("com.fq.day24.Student"); //获取类的所有的 公开 方法,包括继承的 Method[] methods = class1.getMethods(); for (Method m:methods) { System.out.println(m); } //获取类所有的方法,包括非公开的,不包括继承的 Method[] methods1 = class1.getDeclaredMethods(); for (Method m:methods) { System.out.println(m); } //获取无参无返回值的方法 Method methodShow = class1.getMethod("show"); Student s1 = (Student) class1.newInstance(); s1.show(); //name:null,age:0 //反射调用方法 methodShow.invoke(s1);//=s1.show(); //name:null,age:0 //获取带参方法 Method method2 = class1.getMethod("show",String.class); s1.show("北京"); //学生地址:北京 method2.invoke(s1,"杭州"); //=s1.show("北京"); //学生地址:杭州 //获取带返回值的方法 Method getName = class1.getMethod("getName"); String a = s1.getName(); System.out.println(a); //小莲花 String a1 = (String) getName.invoke(s1); System.out.println(a1); //小莲花 //获取私有方法 Method study = class1.getDeclaredMethod("study"); study.setAccessible(true); //将方法的访问修饰符无效 study.invoke(s1); //好好学习 //获取静态方法 Student.exam(); //开始考试 Method exam = class1.getMethod("exam"); exam.invoke(null); // =Student.exam(); //开始考试 } //反射操作5:获取类对象的属性 public static void reflect5() throws Exception{ Class class1 = Class.forName("com.fq.day24.Student"); //获取所有的属性 Field[] fields = class1.getDeclaredFields(); for (Field f:fields) { System.out.println(f); } //获取name属性 Field name = class1.getDeclaredField("name"); Student s1 = (Student) class1.newInstance(); name.setAccessible(true);//访问权限无效 name.set(s1,"小翠"); System.out.println(s1.toString()); //Student{name='小翠', age=0} Field age = class1.getDeclaredField("age"); age.setAccessible(true);//访问权限无效 age.set(s1,23); System.out.println(s1.toString()); //Student{name='小翠', age=23} } }
反射的优点和缺点
-
优点
-
提高了JAVA程序的灵活性和扩展性,降低了耦合性,提高自适应能力
-
允许程旭创建和控制任何类的对象,无需提前硬编码目标类
-
-
缺点
-
性能问题
-
代码维护问题
-
使用反射实现插件开发
package com.fq.day24; public interface CarService { void run(); void turn(String dic); }
package com.fq.day24; public class BaoMa implements CarService{ @Override public void run() { System.out.println("宝马开始奔跑。。。。"); } @Override public void turn(String dic) { System.out.println("宝马向"+dic+"转向"); } }
package com.fq.day24; public class BenChi implements CarService{ @Override public void run() { System.out.println("奔驰开始奔跑。。。。"); } @Override public void turn(String dic) { System.out.println("奔驰向"+dic+"转向"); } }
package com.fq.day24; import java.io.BufferedReader; import java.io.FileReader; public class TestCarService { public static void main(String[] args) throws Exception{ FileReader fr = new FileReader("F:\\workspace\\Java-Idea-workspace\\JavaGP8QF\\Day24(0619)\\car.txt"); BufferedReader br = new BufferedReader(fr); String classname; while ((classname=br.readLine())!=null){ try{ System.out.println(classname); Class class1 = Class.forName(classname); CarService carService = (CarService)class1.newInstance(); carService.run(); carService.turn("北"); }catch (Exception e){ continue; } } } }
内省
-
内省:才用反射机制实现对属性进行操作的一种机制
-
PropertyDescriptor:属性描述符,代表一个属性
-
BeanInfo:实体类信息,包含类的信息
-
Introspector:工具类
-
-
package com.fq.day24; import java.io.Serializable; public class Student implements Serializable { private String name; private int age; public Student(){ } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Student(String name, int age) { this.name = name; this.age = age; } public void show(){ System.out.println("name:"+name+",age:"+age); } public void show(String address){ System.out.println("学生地址:"+address); } public String getName(){ return "小莲花"; } private void study(){ System.out.println("好好学习"); } public static void exam(){ System.out.println("开始考试"); } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
-
package com.fq.day24; import java.beans.BeanInfo; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; public class TestStudent { public static void main(String[] args) throws Exception{ Class<?> class1 = Class.forName("com.fq.day24.Student"); Student s1 = (Student) class1.newInstance(); PropertyDescriptor pd = new PropertyDescriptor("name",class1); Method setName = pd.getWriteMethod(); Object name = "小莲花"; setName.invoke(s1,name); PropertyDescriptor pd1 = new PropertyDescriptor("age",class1); Method setAge = pd1.getWriteMethod(); Object age = 20; setAge.invoke(s1,age); System.out.println(s1.toString()); //Student{name='小莲花', age=20} System.out.println("_--------------------------_"); //如果类中有getXXX(无参有返回值)、setXXX(有参无返回值)、isXXX(无参有返回值,类型是boolean),认为类中有这种属性 //获取类的信息 BeanInfo beanInfo = Introspector.getBeanInfo(class1); //获取属性 PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor p:pds) { System.out.println(p.getName()); //age //class // name } } }