黑马程序员_java反射机制
什么是反射:反射其实就加载类解剖类的组成部分。
通常在写框架时,就需要使用大量的反射技术来完成一些操作。
在java中如何来使用反射技术?
1.获取此类的字节码对象。可以通过java中最常见的三种方式获取。
(1)Class.forName("类的完整路径");//就是包名加类名
(2)类名.class
(3)对象名.getClass();
2.解剖里面类中的组成部分,分别是(成员变量,成员函数,构造函数)。
同过Class类中的一些方法可以实现,分别是:
getFields()//获取此类的所有public修饰的字段 getMethods();获取此类的所有public修饰的函数 getConstructors();//获取此类所有被public修饰的构造函数 getField(name)//获取此类被public修饰名为name的字段 getMethod(name,Types)//获取此类被public修饰名为name,参数为Types的方法,因为参数可以有多个,所以Types是可变参数类型 getConstructor(Types)//根据Types参数获取此类被public修饰的构造函数,Types是可变参数类型。 ---------------------------------------------- getDeclaredFields()//获取此类所有的字段,也包含私有的。 getDeclaredMethods();获取此类的所有的函数,也包含私有的 getDeclaredConstructors();获取此类的所有的构造函数,也包含私有的 getDeclaredField(name)//获取此类中为名name的字段,也包含私有的 getDeclaredMethod(name,Types)//获取此类的名为name,参数为Types的方法,因为参数可以有多个,所以Types是可变参数类型,也包含私有的。
getDeclaredConstructor(Types)//根据Types参数获取此类的构造函数,Types是可变参数类型,也包含私有的。
(1)(通过反射获取字段,并使用)
package Test; import java.lang.reflect.Field;
class Person{ public String name; } public class Demo1 { public static void main(String[] args)throws Exception{ Class clazz=Class.forName("Test.Person");//获得Person类字节码对象 Person p=new Person(); Field fieName=clazz.getField("name"); String str=(String)fieName.get(p);//获取p对象中的name字段的值 } }
(2)(通过反射获取成员函数,并调用)
package Test; import java.lang.reflect.Method; class Person{ public void show(){ System.out.println("我是无参show方法"); } public void show(String name){ System.out.println("我是有参"+name); } } public class Demo1 { public static void main(String[] args)throws Exception{ Class clazz=Class.forName("Test.Person");//获得Person类字节码对象 Person p=new Person(); Method metShow=clazz.getMethod("show",null);//获取无参show方法,没参所以传null Method metShow2=clazz.getMethod("show",String.class);//获取有参show方法。 metShow.invoke(p,null);//用p对象调用此方法 metShow2.invoke(p,"show方法"); } }
(3)(通过反射获取构造函数,并创建对象)
package Test; import java.lang.reflect.Constructor; class Person{ public Person(){ System.out.println("调用无参构造函数创建对象"); } public Person(int age,String name){ System.out.println("调用有参构造函数创建对象"); } } public class Demo1 { public static void main(String[] args)throws Exception{ Class clazz=Class.forName("Test.Person");//获得Person类字节码对象 Constructor constru1=clazz.getConstructor(null);//获取此类的无参构造函数 Constructor constru2=clazz.getConstructor(int.class,String.class);//获取此类多参的构造函数 constru1.newInstance(null);//调用无参构造函数创建对象 constru2.newInstance(34,"黑马_小爻");//调用多参构造函数创建对象 } }
如果是非public修饰的成员如何获取并使用呢?
我就举一个例子,因为其他的都一样
案例(获取非public修饰的成员的函数并调用)
package Test;
import java.lang.reflect.Method;
class Person{
private void show(){
System.out.println("我来了,黑马!!");
}
}
public class Demo1 {
public static void main(String[] args)throws Exception{
Class clazz=Class.forName("Test.Person");
Person p=new Person();
Method method=clazz.getDeclaredMethod("show",null);//由show方法时private的,所以只能通过getDeclaredMethod方法才能获得
method.setAccessible(true);//这里为true代表java使用它时不对其进行访问权限语法检查
method.invoke(p,null);
}
}
有一件事情值得注意,如果方法的参数为数组类型,通过反射获取此方法时一定要记得将数组强转为Object
如:通过反射获取main方法。
package Test;
import java.lang.reflect.Method;
class Person{
public static void main(String[] args){
System.out.println("Person");
}
public static void show(Object[] obj){
System.out.println(obj.length);
}
}
public class Demo1 {
public static void main(String[] args)throws Exception{
Class clazz=Class.forName("Test.Person");
Method met=clazz.getMethod("main",String[].class);
met.invoke(null,(Object)new String[]{"你好黑马"});
/*为什么要将String数组强转为Object对象呢?
* 这是java升级后遗留下来的问题,因为在java1.4版本的时候,还没有可变参数类型时,我们这里参数类型是一个Object[]数组
* 我们把Object数组中的每个角标元素来出来当方法参数。来确定我们要获取的方法
* 1.5有了可变参数后,java为了使旧版本能够兼容新版本,所以只要你传数组,还是按老办法获取方法
* 所以上面的运行实际是把数组拆开后把其中的元素传进去的,并不是把String数组传进去的。
* */
}
}
邮箱:wolaoben7252@qq.com