Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

Java反射机制学习

$
0
0

一.概念

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

JAVA反射(放射)机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。

二.Class类的使用

在面向对象的世界中万事万物皆对象,在java中除了普通数据(但有封装类)和静态类(属于类)不是对象外 其它都为对象。

那么类是对象吗?是谁的对象呢?类是对象,是java.lang.class的类。

反射机制获取类的3中方法

首先我们可以看看class的源代码,会发现这行代码


私有的构造方法,只有java虚拟机才能创建对象   所以我们不可以通过new 来创建对象

但是还有三种其它的方法可以创建对象

package reflect;

/**
 * @author scx
 *Class类的使用
 */
public class Main {
	public static void main(String[] args) {
		Fool fool=new Fool();
		//第一种方式  任何一个类都有一个隐含的静态成员变量class
		Class c1=Fool.class;
		//第二种方式  可以通过类的对象getClass方法
		Class c2=fool.getClass();
		//第三种方式  通过完整的包名和类名
		Class c3=null;
		try {
			c3=Class.forName("reflect.Fool");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		/*
		 * c1,c2,c3代表了Fool类的类类型   是class的实例对象
		 * 这个对象我们称为该类的类类型
		 */
		System.out.println("c1="+c1);
		System.out.println("c2="+c2);
		System.out.println("c3="+c3);
	}
}
//Fool  是java.lang.class的对象
class Fool{}

运行结果

c1=class reflect.Fool

c2=class reflect.Fool
      c3=class reflect.Fool


三.创建对象 newInstance

  
try {
			Fool fool2=(Fool) c1.newInstance();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}


四.动态加载类

1.什么是动态加载类 什么是静态加载类

Class.forName 不仅表示类的类类型,还代表了动态加载类。编译时加载是静态加载类,

运行时加载是动态加载类。

请大家区分编译 运行。

2.为何要使用动态加载类

我们写了一个程序 并没有写A类和B类以及start方法 

public class Main{
	public static void main(String args[]){
		if("A".equals(args[0])){
			A a=new A();
			a.start();
		}
		if("B".equals(args[0])){
			B b=new B();
			b.start();
		}
	}
}


编译:


我们会发现,我们并不一定用到A功能或B功能,可是编译却不能通过。而在日常的项目中,如果我们写了100个功能,因为一个功能的原因而导致所有功能不能使用,明显使我们不希望的。在这里,为什么会在编译时报错呢?new 是静态加载类,在编译时刻就需要加载所有可能使用到的功能。所以会报错。而在日常中我们希望用到哪个就加载哪个,不用不加载,就需要动态加载类。

使用动态加载类时,我们不用定义100种功能,只需要通过实现某种标准(实现某个接口)。

代码:

public class Main{
	public static void main(String args[]){
		try{
			
			Class c=Class.forName(args[0]);
		
			All a=(All)c.newInstance();
			a.start();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}
class A implements All{
	public void start(){
		System.out.println("A....START");
	}
}
class B implements All{
	public void start(){
		System.out.println("B....START");
	}
}
//接口
interface All{
	public void start();
}


总结:推荐大家使用动态加载类。原因如上,即节省了代码,又简洁方便,安全。

学习java反射的时候 看到了这 理解的比较浅显  ,肯定有许多要补充的。慢慢学习 慢慢积累  欢迎评论

五.获取类的方法信息

  getMethods()方法获取的是所有的public的函数 包括父类继承
 getDeclaredMethods()方法获取的是所有该类自己声明的方法

package reflect;

import java.lang.reflect.Method;

public class ClassDemo {
	public static void main(String[] args) {
		//获取类的信息 首先获取类类型
		Class c=Book.class;
		//获取包名+类名
		System.out.println(c.getName());
		//获取类名
		System.out.println(c.getSimpleName());
		/*
		 * Method类 方法对象
		 * 一个成员就是一个Method对象
		 * getMethods()方法获取的是所有的public的函数 包括父类继承
		 * getDeclaredMethods()方法获取的是所有该类自己声明的方法
		 */
		Method []ms=c.getDeclaredMethods();
		for(Method method:ms){
			//得到方法的返回值类型的类类型
			Class returnType=method.getReturnType();
			System.out.print("返回值类型:"+returnType+"\t");
			//得到方法的名称
			System.out.print(method.getName()+"(");
			//获取参数的类类型
			Class[] paramTypes=method.getParameterTypes();
			for (Class paramType : paramTypes) {
				System.out.print(paramType.getName()+" ");
			}
			System.out.println(")");
		}
	}
}
class Book extends Rect{
	private int price;
	private String name;
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
class Rect{
	private int width;
	private int height;
	public void setRect(int width,int height){
		this.width=width;
		this.height=height;
	}
}

运行结果:


当然还有获得类的成员变量  构造方法 ,实现接口,父类,访问权限,包名,等等。

只要我们记得 无论获得什么  首先要获取类的类类型 ,其它通过阅读api文档  轻而易举~


六.获取指定的方法

getDeclaredMethod(name, parameterTypes)  name为方法名  parameterTypes为参数类型数组

举个例子

package reflect;
import java.lang.reflect.Method;

public class MethodDemo1 {
	public static void main(String[] args) throws Exception {
		/*
		 * 若想获取print方法 首先获得类的信息 若想获得类的信息 首先获取类类型
		 */
		
		A a = new A();
		Class c = A.class;
		Method m1 = c.getDeclaredMethod("print", int.class, int.class);
		// 方法的反射操作 invoke方法  第一个参数为要操作的对象
		Object o = m1.invoke(a, 5, 6);// 和a1.print(5,6) 同样效果 
		Method m2=c.getDeclaredMethod("print",String.class,String.class);
		Object o2=m2.invoke(a,"Hello","World");//和a1.print(Hello,World) 同样效果
		
		Method m3=c.getDeclaredMethod("print");
		Object o3=m3.invoke(a);//和a1.print() 同样效果 
	}
}

class A {
	public void print(){
		System.out.println("A");
	}
	public void print(int a, int b) {
		System.out.println(a + b);
	}

	public void print(String a, String b) {
		System.out.println(a.toLowerCase() + b.toUpperCase());
	}
}

运行结果:

11
helloWORLD
A


作者:su20145104009 发表于2016/10/26 17:39:19 原文链接
阅读:45 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>