JAVA中反射是什么?

能够分析能力的程序成为反射,通俗的来讲就是能够通过运行时的类名获取类的全部信息。反射机制可以用来干以下的事情:

1、在运行时分析类的能力

2、在运行时查看对象,例如,编写一个toString()方法供所有类使用

3、实现通用的数组操作代码

4、利用Method对象,这个对象很像C++中的函数指针

下面来说一说他的底层实现原理:

在程序运行期间,JVM始终对所有的对象都有跟踪,并且将其所有信息存入一个类型为Class的对象中,选择对应的方法进行执行,即在程序运行时自动分析需要使用的类,并且通过newInstance()的方法动态的加载类。

反射的应用:

先看一下如下例子:

在没有使用反射时,每次增加一个水果都需要修改Factory中的代码,这样会很麻烦的

interface fruit{  
    public abstract void eat();  
}  
    
class Apple implements fruit{  
    public void eat(){  
        System.out.println("Apple");  
    }  
}  
    
class Orange implements fruit{  
    public void eat(){  
        System.out.println("Orange");  
    }  
}  
    
// 构造工厂类  
// 也就是说以后如果我们在添加其他的实例的时候只需要修改工厂类就行了  
class Factory{  
    public static fruit getInstance(String fruitName){  
        fruit f=null;  
        if("Apple".equals(fruitName)){  
            f=new Apple();  
        }  
        if("Orange".equals(fruitName)){  
            f=new Orange();  
        }  
        return f;  
    }  
}  
class hello{  
    public static void main(String[] a){  
        fruit f=Factory.getInstance("Orange");  
        f.eat();  
    }  
    
}  

使用反射:

interface fruit{  
    public abstract void eat();  
}  
   
class Apple implements fruit{  
    public void eat(){  
        System.out.println("Apple");  
    }  
}  
   
class Orange implements fruit{  
    public void eat(){  
        System.out.println("Orange");  
    }  
}  
   
class Factory{  
    public static fruit getInstance(String ClassName){  
        fruit f=null;  
        try{  
            f=(fruit)Class.forName(ClassName).newInstance();  //forName使用反射获取类,newInstance获取实例
        }catch (Exception e) {  
            e.printStackTrace();  
        }  
        return f;  
    }  
}  
class hello{  
    public static void main(String[] a){  
        fruit f=Factory.getInstance("Reflect.Apple");  
        if(f!=null){  
            f.eat();  
        }  
    }  
}

 这样一来,我们就不用在每一次增加水果种类时修改Factory类,由此可以看到反射的好处,那么问题来了,为什么不在任何地方都使用反射呢,这是因为,反射虽然节省了操作,但是他所占用的资源开销是很大的,因此我们要根据实际情况使用反射。

下面来说一下反射的具体使用方法:

java.lang.reflect包中有三个类Filed、Method、Constructor分别用于描述类的域、方法、构造器。这三个类都有一个getName()的方法,用来返回项目的名称。此外三个类中都有一个getModifiers()方法,用来分析访问修饰符使用情况。

获得构造函数的方法 
    Constructor getConstructor(Class[] params)//根据指定参数获得public构造器

    Constructor[] getConstructors()//获得public的所有构造器

    Constructor getDeclaredConstructor(Class[] params)//根据指定参数获得public和非public的构造器

    Constructor[] getDeclaredConstructors()//获得public的所有构造器 

获得类方法的方法 
    Method getMethod(String name, Class[] params),根据方法名,参数类型获得方法

    Method[] getMethods()//获得所有的public方法

    Method getDeclaredMethod(String name, Class[] params)//根据方法名和参数类型,获得public和非public的方法

    Method[] getDeclaredMethods()//获得所以的public和非public方法 

获得类中属性的方法 
    Field getField(String name)//根据变量名得到相应的public变量

    Field[] getFields()//获得类中所以public的方法

    Field getDeclaredField(String name)//根据方法名获得public和非public变量

    Field[] getDeclaredFields()//获得类中所有的public和非public方法

示例如下:

package test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Scanner;

public class Tresgt {
	
		public static void main(String args[]) {
			String name = "test.test121";
//			if(args.length>0)name=args[0];
//			else {
//				Scanner in =new Scanner(System.in);
//				System.out.println("Enter class name (e.g.java.until.Date):");
//				name=in.next();
//			}
			try {
				Class c1=Class.forName(name);
				Class superc1=c1.getSuperclass();
				System.out.println("----------------------"+c1.getModifiers());
				String modifiers=Modifier.toString(c1.getModifiers());
				if(modifiers.length()>0)
					System.out.println(modifiers+"");
				System.out.println("class:"+name);
				if(superc1!=null&&superc1!=Object.class)
					System.out.println("extends"+superc1.getName());
				System.out.println("\n{\n");
				System.out.println("------------------------------------");
				printConstructors(c1);
				System.out.println();
				System.out.println("------------------------------------");
				printMethods(c1);
				System.out.println();
				System.out.println("------------------------------------");
				printFields(c1);
				System.out.println("}");
			}
			catch(ClassNotFoundException e) {
				e.printStackTrace();
			}
			System.exit(0);
		}

	public static void printConstructors(Class c1){
		Constructor[] contructors = c1.getConstructors();
		for(Constructor c : contructors){
			String name = c.getName();
			System.out.print(" ");
			String m = Modifier.toString(c.getModifiers());
			if(m.length() > 0)
				System.out.print(m+" ");
			System.out.print(name + "(");
			Class[] p = c.getParameterTypes();
			for(int j = 0 ; j < p.length;j++){
				if(j> 0)
					System.out.print(", ");
				System.out.print(p[j].getName());
			}
			System.out.println(");");
		}
		
	}
	
	
	
	public static void printFields(Class c1) {
		Field[] fields = c1.getFields();
		
		for(Field f:fields) {
			Class type =f.getType();
			String name= f.getName();
			System.out.print("");
			String modifiers=Modifier.toString(f.getModifiers());
			if(modifiers.length()>0)
				System.out.print(modifiers+"");
			System.out.println(type.getName()+""+name+";");
			
		}
	}
	
	
	
	
	public static void printMethods(Class cl)
	{
		Method[] methods = cl.getMethods();
		for(Method m : methods)
		{
			Class retType = m.getReturnType();
			String name = m.getName();
			System.out.println(" ==========--------  ");
			String modifiers = Modifier.toString(m.getModifiers());
			if(modifiers.length() > 0)
			{
				System.out.println(modifiers+"");
			}
			System.out.print(retType.getName()+" "+name+"(");
			Class[] paramTypes=m.getParameterTypes();
			for(int j=0;j<paramTypes.length;j++)
			{
				if(j>0)
				{
					System.out.println(",");
				}
				System.out.println(paramTypes[j].getName());
			}
			System.out.println(");");
		}
	}

}

结果:

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值