所有的框架和服务器开发都是用的反射技术,学好反射对日后更深层次的开发是非常重要的。
通过反射可以动态的获取类的成员,在不想改动源代码的情况下修改类,这样我们就可以通过反射技术将这个类加载进来。我们在框架用xml文件进行配置的时候,实际上就是获取到类名使用反射动态的加载进来,大大提高了可扩展性,另外再访问私有属性的时候是访问不到的,因为它不可见,如果非要访问的话可以用暴力反射进行访问
实例:
/*
* 执行字节码文件中一个方法。
*/
private static void getSingleMethod() throws ClassNotFoundException, Exception, Exception {
"cn.test.demo.Person");
//指定要运行的方法
"show2", null);
//调用此方法并运行
null);
}
/*
* 当动态加载的类中的没有空参数构造函数时。
* 需要获取指定的构造函数进行该字节码文件对象的初始化。
*/
private static void getConstructor() throws Exception {
"cn.test.demo.Person");
//获取到指定参数类型的构造函数对象。
class);
//通过构造器创建该类的实例
"zhangan");
//获取要调用的方法
"show",int.class);
//执行方法,获取返回值
88);
"str="+str);
}
/*
* 获取指定类中的方法。
*/
private static void getClassMethod() throws ClassNotFoundException {
"cn.test.demo.Person");
//获取包括父类的方法,只能获取共有的方法
Method[] methods = clazz.getMethods();
//不能获取父类的方法可以获取指定类的私有和共有的方法
methods = clazz.getDeclaredMethods();
for(Method m : methods){
System.out.println(m.toString());
}
}
/*
* 获取字节码文件对象的三种方式
*/
private static void demoGetClass() throws ClassNotFoundException {
//方式一,getClass();
new Person();
Class clazz = p.getClass();
System.out.println(clazz.getName());
//方式二,每一个类都有一个属性 .class.
class;
System.out.println(c2.getName());
//方式三,通过Class类中的一个static方法forName获取一个字节码文件对象。
//给forName传值必须是类的全名称。
"cn.test.demo.Person");
System.out.println(c3.getName());
}
Person.java:
public class Person {
private String name;
public Person(){
"person run");
}
public Person(String name){
this.name =name;
"-------------");
}
public String show(int num){
"num="+num+"--show run--"+name);
return "hahha";
}
public void show2(){
"------123-------");
}
public void haha(String s){
"haha="+s);
}
private void function(){
"functio run");
}
}
总结:
1.加载类的三种方式:
//加载类方法1:
String classname ="cn.itcast.bean.Person";
Class clazz1=Class.forName(classname); //获取类的字节码拿到类
//加载类方法2:
Class clazz2=Person.class; //在框架中用的不多
//加载类方法3:
Class clazz3=new Person().getClass();
2.反射构造方法创建类的实例:
构造函数有四种方式:无参、有参、多个参数、私有构造函数。
public Person(){}
public Person(String name){
this.name=name;
}
public Person(String name,List list){
}
private Person(Set set){
}
针对以上四种构造方法的反射如下:
[java]
view plain
copy
//反射无参的构造函数
@Test
public void test2 () throws Exception{
"cn.itcast.bean.Person";
//加载类
null);//拿到无参的构造函数
null); //创建实例对象
System.out.println(obj);
}
//反射有参的构造函数
@Test
public void test3 () throws Exception{
"cn.itcast.bean.Person";
Class clazz1=Class.forName(classname);
class);//拿到有参的构造函数
"aaa"); //创建实例对象
System.out.println(obj);
}
//反射有多个参数的构造函数
@Test
public void test4 () throws Exception{
"cn.itcast.bean.Person";
Class clazz1=Class.forName(classname);
class,List.class);//拿到多个参数的构造函数
"bbb",new ArrayList());
System.out.println(obj);
}
//反射私有的构造函数
@Test
public void test5 () throws Exception{
"cn.itcast.bean.Person";
Class clazz1=Class.forName(classname);
class);//得到类里面声明的成员
true); //暴力反射
new HashSet());
System.out.println(obj);
}
3.反射方法:
方法共有五几种形态:
public void a1(){
"hahaa");
}
public void a2(String name){
System.out.println(name);
}
public String a3(String name ,String password){
return name+password;
}
private String a4(List list){
return list.toString();
}
private static void a5(String arr[]){
System.out.println(Arrays.asList(arr));
}
针对五种形态的反射方法如下:
//反射无参方法
@Test
public void test1() throws Exception{
new Person();
"cn.itcast.bean.Person");//拿到类
"a1",null); //反射无参数的构造方法
null); //执行无参构造方法
}
//反射一个参数的方法
@Test
public void test2() throws Exception{
new Person();
"cn.itcast.bean.Person");
"a2",String.class); //反射有参数的构造方法
"aaaaa");
}
//反射多个参数的方法
@Test
public void test3() throws Exception{
new Person();
"cn.itcast.bean.Person");
"a3",String.class,String.class);
"aaaaa","bbbbbb");
System.out.println(result);
}
//反射私有的方法
@Test
public void test4() throws Exception{
new Person();
"cn.itcast.bean.Person");
"a4",List.class); //得到声明的方法
true); //暴力反射
new ArrayList());
System.out.println(result);
}
//反射私有的静态方法
@Test
public void test5() throws Exception{
"cn.itcast.bean.Person");
"a5",String [].class);
true); //暴力反射
null,(Object)new String []{"1","2"});
}
4.反射字段
反射私有字段
//反射私有字段
@Test
public void test1() throws Exception{
new Person();
"cn.itcast.bean.Person");
"name"); //拿到字段
true);
"frk"); //封装值
//得到值
System.out.println(name);
}