JAVA 反射

来源:互联网 发布:linux强制删除受损文件 编辑:程序博客网 时间:2024/06/06 04:23

一、关于反射


下面的代码是关于一个Student类复写equals方法:

 @Override      public boolean equals(Object obj) {          // TODO Auto-generated method stub          if (!(obj instanceof Student))              return false;          Student student = (Student) obj;          return this.name.equals(student.name) && this.age == student.age;      }  

其中要先判断传进来的obj是否就是Student的一个实例 ,也就是说虚拟机在不运行这段代码前,根部不知道Object obj具体是什么类,通过运行obj instanceof Student的返回结果来判断。

在JDK中包含了许多类String、 Integer、ArrayList、HashMap,假如把这些【java类】事物抽象成一个类即【java类】类,那么String类、Integer等等就是【java类】类的不同实例了。

java用Class来代表【java类】这种类型,而通过一个类的实例或类来获取具体是哪一个【Java类】

如:

Class clazz1=obj.getClass();//通过一个实例对象

Class clazz2=Student.class;//直接通过类.class

这就是反射,通过类或类实例获取【Java类】类

如果clazz1==clazz2 就说明obj一定是Student类型的,所以obj instanceof Student也可以用反射的方式:


@Overridepublic boolean equals(Object obj) {// TODO Auto-generated method stubif (!(obj.getClass() == Student.class))return false;Student student = (Student) obj;return this.name.equals(student.name) && this.age == student.age;}


关于静态编译和动态编译

静态编译:在编译时确定类型,绑定对象,如以往获取对象实例是Student student=new Student(),程序在运行前就去定了哪种操作对象或类型。


动态编译:运行时确定类型,绑定对象。具体要创建的对象类型可以通过外部参数来确定,动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。spring的IOC就是利用反射原理将生成新对象的过程交给配置文件。想要新建什么类型的对象就配置XML,BeanFactory解析XML,通过反射新建实例。

因此可以看出反射的优越性,但是反射也有其缺点就是效率较低。


二、获取Class

上面的提到了 实例.getClass() 和 某类.class 两种获取Class的方法外 还可以通过类名的字符串获取 即:

Class.forName("com.heima.Student");

代码:

public static void main(String[] args) throws Exception{Student student=new Student(11, "黑马");Class  clazz1=Student.class;Class  clazz2=student.getClass();Class  clazz3=Class.forName("Blog.Student");System.out.println(clazz1==clazz2);System.out.println(clazz1==clazz3);}
打印:

true
true


同样,基本数据类型也可以通过.class获取 ,除此之外还可以通过包装类.Type来获取,包装类.Type和包装类.class 获取的Class是不相同的。

public static void main(String[] args) throws Exception{Class clazz_int=int.class;Class clazz_boolean=boolean.class;//基本类型的classClass clazz_Integer=Integer.class;Class clazz_Boolean=Boolean.class;//包装类的classClass integer_type=Integer.TYPE;Class boolean_type=Boolean.TYPE;//基本类型的classSystem.out.println("clazz_int==clazz_Integer:"+(clazz_int==clazz_Integer));System.out.println("clazz_int==integer_type:"+(clazz_int==integer_type));System.out.println("clazz_boolean==clazz_Boolean:"+(clazz_boolean==clazz_Boolean));System.out.println("clazz_boolean==boolean_type:"+(clazz_boolean==boolean_type));}

打印结果:

clazz_int==clazz_Integer:false
clazz_int==integer_type:true
clazz_boolean==clazz_Boolean:false
clazz_boolean==boolean_type:true


三、获取类信息

一个类的信息都存储对应的一个Class实例当中,得到Class的实例就能获取这个类的基本信息。

public static void main(String[] args) {Class<Student> clazz = Student.class; //得到包名clazz.getPackage();//得到全限定名clazz.getName();//得到类的简称clazz.getSimpleName();//得到父类的classSystem.out.println(clazz.getSuperclass());//获得public修饰的内部类和接口Class[] clzzs = clazz.getClasses();for (Class class1 : clzzs) {System.out.println(class1.getName());}}


四、获取成员方法、构造方法、成员变量

以Person类为例:

public class Person implements Serializable{private static final long serialVersionUID = -4102534291757583600L;private String name;private Integer age;public String add;public Person(String name, Integer age) {super();this.name = name;this.age = age;}public Person(String name, Integer age, String add) {super();this.name = name;this.age = age;this.add = add;}public Person() {// TODO Auto-generated constructor stub}public void setName(String name) {this.name = name;}public void setAge(Integer age) {this.age = age;}public void setAdd(String add) {this.add = add;}public String getAdd() {return add;}public String getName() {return name;}public Integer getAge() {return age;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + ((add == null) ? 0 : add.hashCode());result = prime * result + ((age == null) ? 0 : age.hashCode());return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;Person other = (Person) obj;if (add == null) {if (other.add != null)return false;} else if (!add.equals(other.add))return false;if (age == null) {if (other.age != null)return false;} else if (!age.equals(other.age))return false;if (name == null) {if (other.name != null)return false;} else if (!name.equals(other.name))return false;return true;}}


获取构造方法相关 以及反射方式创建实例

public static void main(String[] args) throws Exception {Class<Person> clazz = Person.class;Constructor<Person> constructor = clazz.getConstructor();// 获取空构造方法Person person = constructor.newInstance();// 新建实例对象//constructor = clazz.getConstructor(String.class, Integer.class, String.class);// 获取带参数的Public构造方法、传入参数类型以确定具体哪一个构造方法 //person = constructor.newInstance("zhangsan", 11, "beijing");constructor = clazz.getDeclaredConstructor(String.class, Integer.class, String.class);// 暴力获取带参数的构造方法、传入参数类型以确定具体哪一个构造方法constructor.setAccessible(true);//暴力破解必须将Accessible设为True,否则会报Exception in thread "main" java.lang.NoSuchMethodExceptionperson = constructor.newInstance("zhangsan", 11, "beijing");Constructor<?>[] constructors = clazz.getDeclaredConstructors();//暴力或取所有构造方法  返回构造方法数组for (Constructor<?> newconstructor : constructors) {//遍历每一个构造方法System.out.println(newconstructor);Class<?>[] ParameterType=newconstructor.getParameterTypes();//获取参数数组for (Class<?> class1 : ParameterType) {//遍历参数数组System.out.println(class1.getName());//获取参数类型名}System.out.println("-----------------");}
打印结果:



获取成员方法相关 以及并通过反射调用方法

public class ClassTest {public static void main(String[] args) throws Exception {Class<Person> clazz = Person.class;Constructor<Person> constructor = clazz.getConstructor();// 获取空构造方法Person person = constructor.newInstance();// 新建实例对象//constructor = clazz.getConstructor(String.class, Integer.class, String.class);// 获取带参数的Public构造方法、传入参数类型以确定具体哪一个构造方法 //person = constructor.newInstance("zhangsan", 11, "beijing");constructor = clazz.getDeclaredConstructor(String.class, Integer.class, String.class);// 暴力获取带参数的构造方法、传入参数类型以确定具体哪一个构造方法constructor.setAccessible(true);//暴力破解必须将Accessible设为True,否则会报Exception in thread "main" java.lang.NoSuchMethodExceptionperson = constructor.newInstance("zhangsan", 11, "beijing");Method[] methods = clazz.getMethods();// 获取public 成员方法methods = clazz.getDeclaredMethods();// 暴力或取成员方法for (Method method : methods) {System.out.println(method);Class<?>[] ParameterType = method.getParameterTypes();for (Class<?> parameter : ParameterType) {System.out.println(parameter);}System.out.println("-----------------");}clazz.getMethod("setName", String.class).invoke(person, "aaa");// 获取特定方法并通过反射调用方法System.out.println(person.getName());}}
打印结果:


获取成员相关 以及反射方式赋值

public static void main(String[] args) throws Exception {Class<Person> clazz = Person.class;Constructor<Person> constructor = clazz.getConstructor();// 获取空构造方法Person person = constructor.newInstance();// 新建实例对象//constructor = clazz.getConstructor(String.class, Integer.class, String.class);// 获取带参数的Public构造方法、传入参数类型以确定具体哪一个构造方法 //person = constructor.newInstance("zhangsan", 11, "beijing");constructor = clazz.getDeclaredConstructor(String.class, Integer.class, String.class);// 暴力获取带参数的构造方法、传入参数类型以确定具体哪一个构造方法constructor.setAccessible(true);//暴力破解必须将Accessible设为True,否则会报Exception in thread "main" java.lang.NoSuchMethodExceptionperson = constructor.newInstance("zhangsan", 11, "beijing");Field[] fields = clazz.getDeclaredFields();//暴力或取成员数组for (Field field : fields) {//便利成员System.out.println(field.getName());}Field field=clazz.getDeclaredField("name");field.setAccessible(true);//允许暴力获取field.set(person, "黑马");;System.out.println(person.getName());}
打印结果:


0 0
原创粉丝点击