`

Java_反射

    博客分类:
  • Java
 
阅读更多

ref: http://blog.csdn.net/liujiahan629629/article/details/18013523

 

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

Java反射机制主要提供了以下功能:

在运行时判断任意一个对象所属的类;

在运行时构造任意一个类的对象;

在运行时判断任意一个类所具有的成员变量和方法;(当然可以调用到private的方法)

在运行时调用任意一个对象的方法;

生成动态代理。

 

实现Java反射的类

1)Class:它表示正在运行的Java应用程序中的类和接口

2)Field:提供有关类或接口的属性信息,以及对它的动态访问权限

3)Constructor:提供关于类的单个构造方法的信息以及对它的访问权限

4)Method:提供关于类或接口中某个方法信息

注意:Class类是Java反射中最重要的一个功能类,所有获取对象的信息(包括:方法/属性/构造方法/访问权限)都需要它来实现

 

 

二,反射机制的作用:

 1,反编译:.class-->.java

 2,通过反射机制访问java对象的属性,方法,构造方法等;

这样好像更容易理解一些,下边我们具体看怎么实现这些功能。

 

三,在这里先看一下sun为我们提供了那些反射机制中的类:

java.lang.Class;                

java.lang.reflect.Constructor; java.lang.reflect.Field;        

java.lang.reflect.Method;

java.lang.reflect.Modifier;

 

四,具体功能实现:

1,反射机制获取类有三种方法,我们来获取Employee类型

//第一种方式:  

Classc1 = Class.forName("Employee");  

//第二种方式:  

//java中每个类型都有class 属性.  

Classc2 = Employee.class;  

//第三种方式:  

//java语言中任何一个java对象都有getClass 方法  

Employeee = new Employee();  

Classc3 = e.getClass(); //c3是运行时类 (e的运行时类是Employee)  

 

2,创建对象:获取类以后我们来创建它的对象,利用newInstance:

Class c =Class.forName("Employee");  

//创建此Class 对象所表示的类的一个新实例  

Objecto = c.newInstance(); //调用了Employee的无参数构造方法.  

 

3,获取属性:分为所有的属性和指定的属性:

      a,先看获取所有的属性的写法:

//获取整个类  

            Class c = Class.forName("java.lang.Integer");  

            Field[] fs = c.getDeclaredFields();  //获取所有的属性

 

            StringBuffer sb = new StringBuffer();  //定义可变长的字符串,用来存储属性

            //通过追加的方法,将每个属性拼接到此字符串中  

            //最外边的public定义

            sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() +"{\n");  

            //里边的每一个属性  

            for(Field field:fs){  

                sb.append("\t");//空格  

                sb.append(Modifier.toString(field.getModifiers())+" ");//获得属性的修饰符,例如public,static等等  

                sb.append(field.getType().getSimpleName() + " ");//属性的类型的名字  

                sb.append(field.getName()+";\n");//属性的名字+回车  

            }  

            sb.append("}");  

            System.out.println(sb);  

 

b,获取特定的属性,对比着传统的方法来学习:

public static void main(String[] args) throws Exception{  

    //以前的方式:  

    /* 

    User u = new User(); 

    u.age = 12; //set 

    System.out.println(u.age); //get 

    */  

 

    Class c = Class.forName("User");   //获取类

    Field idF = c.getDeclaredField("id");   //获取id属性

    Object o = c.newInstance();   //实例化这个类赋给o

    idF.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。  

    idF.set(o, "110"); //给o对象的id属性赋值"110"

    System.out.println(idF.get(o));  

}  

4,获取方法,和构造方法,不再详细描述,只来看一下关键字:

方法关键字

含义

getDeclaredMethods()

获取所有的方法

getReturnType()

获得方法的放回类型

getParameterTypes()

获得方法的传入参数类型

getDeclaredMethod("方法名",参数类型.class,…)

获得特定的方法

 

 

构造方法关键字

含义

getDeclaredConstructors()

获取所有的构造方法

getDeclaredConstructor(参数类型.class,…)

获取特定的构造方法

 

 

父类和父接口

含义

getSuperclass()

获取某类的父类

getInterfaces()

获取某类实现的接口

 

这样我们就可以获得类的各种内容,进行了反编译。对于JAVA这种先编译再运行的语言来说,反射机制可以使代码更加灵活,更加容易实现面向对象。

 

五,反射加配置文件,使我们的程序更加灵活:

在设计模式学习当中,学习抽象工厂的时候就用到了反射来更加方便的读取数据库链接字符串等,当时不是太理解,就照着抄了。看一下.NET中的反射+配置文件的使用:

当时用的配置文件是app.config文件,内容是XML格式的,里边填写链接数据库的内容:

<configuration>  

<appSettings>  

<add key=""  value=""/>  

</appSettings>  

</configuration>  

 

反射的写法:   assembly.load("当前程序集的名称").CreateInstance("当前命名空间名称".要实例化的类名);  

 

这样的好处是很容易的方便我们变换数据库,例如我们将系统的数据库从SQL Server升级到Oracle,那么我们写两份D层,在配置文件的内容改一下,或者加条件选择一下即可,带来了很大的方便。

当然了,JAVA中其实也是一样,只不过这里的配置文件为.properties,称作属性文件。通过反射读取里边的内容。这样代码是固定的,但是配置文件的内容我们可以改,这样使我们的代码灵活了很多!

综上为,JAVA反射的再次学习,灵活的运用它,能够使我们的代码更加灵活,但是它也有它的缺点,就是运用它会使我们的软件的性能降低,复杂度增加,所以还要我们慎重的使用它。

 

---------------------------------------------------

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class TestReflection {
	private String username;
	private String password;
	private int[] age;
	public void setUserName(String username) {
		this.username = username;
	}
	private void setPassWord(String password) {
		this.password = password;
	}
	
	public static void test01() throws ClassNotFoundException {
		Class c1 = TestReflection.class;
		Class c2 = Class.forName("ran.reflection.demo.TestReflection");
		
		//获取指定的包名
		String package01 = c1.getPackage().getName();
		String package02 = c2.getPackage().getName();
		System.out.println("package01 = " + package01);
		System.out.println("package02 = " + package02);
		
		//获取类的修饰符
		int mod = c1.getModifiers();
		String modifier = Modifier.toString(mod);
		System.out.println("modifier = " + modifier);
		
		//获取指定类的完全限定名
		String className = c1.getName();
		System.out.println("className = " + className);
		
		//获取指定类的父类
		Class superClazz = c1.getSuperclass();
		String superClazzName = superClazz.getName();
		System.out.println("superClazzName = " + superClazzName);
		
		//获取实现的接口
		Class[] interfaces = c1.getInterfaces();
		for (Class t : interfaces) {
			System.out.println("interfacesName = " + t.getName());
		}
		
		//获取指定类的成员变量
		Field[] fields = c1.getDeclaredFields();
		for (Field field : fields) {
			modifier = Modifier.toString(field.getModifiers()); //获取每个字段的访问修饰符
			Class type = field.getType(); //获取字段的数据类型所对应的
			String name = field.getName(); //获取字段名Class对象
			if (type.isArray()) { //如果是数组类型则需要特别处理
				String arrType = type.getComponentType().getName() + "[]";
				System.out.println("" + modifier + " " + arrType + " " + name + ";");
			} else {
				System.out.println("" + modifier + " " + type + " " + name + ";");
			}
		}
		//获取类的构造方法
		Constructor[] constructors = c1.getDeclaredConstructors();
		for (Constructor constructor : constructors) {
			String name = constructor.getName(); //构造方法名
			modifier = Modifier.toString(constructor.getModifiers()); //获取访问修饰符
			System.out.println("" + modifier +" " + name + "(");
			Class[] paramTypes = constructor.getParameterTypes(); //获取构造方法中的参数
			for (int i = 0; i < paramTypes.length; i++) {
				if (i > 0) {
					System.out.print(",");
				}
				if (paramTypes[i].isArray()) {
					System.out.println(paramTypes[i].getComponentType().getName()+"[]");
				} else {
					System.out.print(paramTypes[i].getName());
				}
			}
			System.out.println(");");
		}
		//获取成员方法
		Method[] methods = c1.getDeclaredMethods();
		for (Method method: methods) {
			modifier = Modifier.toString(method.getModifiers());
			Class returnType = method.getReturnType(); //获取方法的返回类型
			if (returnType.isArray()) {
				String arrType = returnType.getComponentType().getName()+"[]";
				System.out.print(""+modifier+" " + arrType + " " + method.getName() + "(");
			} else {
				System.out.print("" + modifier + " " + returnType.getName() + " " + method.getName() + "(");
			}
			Class[] paramTypes = method.getParameterTypes();
			for (int i = 0; i < paramTypes.length; i++) {
				if (i > 0) {
					System.out.print(",");
				}
				if (paramTypes[i].isArray()) {
					System.out.println(paramTypes[i].getComponentType().getName()+"[]");
				} else {
					System.out.print(paramTypes[i].getName());
				}
			}
			System.out.println(");");
		}
	}
	
	public static void test02() throws InstantiationException,IllegalAccessException, SecurityException, NoSuchMethodException,IllegalArgumentException, InvocationTargetException {
		//反射调用方法,可以通过Method类的invoke方法实现动态方法的调用
		//public Object invoke(Object obj, Object... args)
		//第一个参数代表对象
		//第二个参数代表执行方法上的参数
		//若反射要调用类的某个私有方法,可以在这个私有方法对应的Mehtod对象上先
		
		//调用setAccessible(true)
		Class c1 = TestReflection.class;
		TestReflection t1 = (TestReflection) c1.newInstance(); //利用反射来创
		//建类的对象
		System.out.println("username == " + t1.username);
		System.out.println("password == " + t1.password);
		Method method = c1.getDeclaredMethod("setUserName", String.class);
		method.invoke(t1, "Java反射的学习");
		System.out.println("username == " + t1.username);
		method = c1.getDeclaredMethod("setPassWord", String.class);
		method.setAccessible(true);
		method.invoke(t1, "反射执行某个Private修饰的方法");
		System.out.println("password == " + t1.password);
	}
	
	public static void main(String[] args) throws ClassNotFoundException,SecurityException, IllegalArgumentException, InstantiationException,IllegalAccessException, NoSuchMethodException, InvocationTargetException {
		test01();
		//test02();
	}
}

 

分享到:
评论

相关推荐

    java_反射实战代码

    与直接在源代码中的交互是一样的,但又提供了额外的在运行时候的灵活性,但反射的一个最大的弊端就是性能比较差,相同的操作,用反射API所需的时间大概比直接使用慢一两个数量级,不过现在的JVM实现中,java反射的...

    Javafanshe.rar_java 反射_java反射_反射_反射机制

    Java反射是Java编程语言中的一个重要特性,它允许运行时的Java程序访问并操作类、接口、字段和方法等对象的内部信息,即使这些信息在编译时并不知道。这一机制使得Java具有了高度的动态性,能够实现元编程,即在程序...

    Reflection_in_Java.zip_in_java 反射_java 反射机制_java反射_反射机制

    Java反射机制是Java编程语言中一个强大的特性,它允许运行时的程序动态地获取类的信息并操作类的对象。在Java中,反射主要涉及到`java.lang.Class`类、`java.lang.reflect`包下的类如`Constructor`、`Method`和`...

    Java__反射.mp4

    Java__反射.mp4

    Java_Reflection_Programming.rar_Agent_java programming_反射

    Java反射编程是Java语言中的一个强大特性,它允许运行时检查类、接口、字段和方法的信息,甚至在没有明确实例化对象的情况下创建和操作对象。这个"Java_Reflection_Programming.rar_Agent_java programming_反射...

    SE_JAVA_EXP_E046.zip

    此外,还可能涉及反射、泛型、枚举、注解等Java特性。反射允许在运行时检查类的信息,创建和调用对象;泛型提供类型安全,避免强制类型转换;枚举可以创建固定数量的常量;注解则是一种元数据,可以用来提供编译时或...

    Java API 中文版 Java_Help_CHS.chm

    7. **反射机制**:Java的反射API允许在运行时动态地获取类的信息(如类名、方法名、参数类型等)并调用它们,增强了程序的灵活性和动态性。 8. **注解(Annotation)**:注解是元数据的一种形式,用于提供编译时和...

    java_经典Socket编程_反射

    **知识点描述**: 了解Java反射的概念,掌握如何通过反射获取对象的信息(类、属性、方法和构造器)。 **详细说明**: - **反射概念**: - 反射是Java的一种特性,允许程序在运行时获取类和对象的信息,并动态操作...

    张利国_Java高端培训系列视频__Java开发专题_反射.rar

    Java反射是Java编程语言中的一个强大特性,它允许程序在运行时检查类、接口、字段和方法的信息,并能动态地创建对象和调用方法。在"张利国_Java高端培训系列视频__Java开发专题_反射.rar"这个压缩包中,我们可以预见...

    JAVA_内部类_反射机制

    然而,反射操作相对低效,因为它需要Java虚拟机在运行时解析类信息,因此应谨慎使用,避免过度依赖反射,尤其是在性能敏感的代码中。 总之,Java的内部类提供了灵活的类设计能力,特别是对于继承和多态的需求,而...

    java_diary_18.rar_JFC_swing_反射机制_国际化 java

    Day01:java环境与数据类型 Day02:数据运算与数组 Day03:面向对象 Day04:修饰符与类权限 Day05:类与接口 Day06:集合类型 Day07:反射机制与内部类 Day08:异常与Swing图形界面 Day09:swing图形界面与AWT事件...

    fanshe_JAVA.zip_java 反射

    Java反射是Java编程语言中的一个核心特性,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。在Java中,反射机制主要涉及类的动态加载、对象的动态创建以及方法的动态调用等。这个名为"fanshe_...

    Programmation_Orientée_Objet_Java_2020-2021_java_Java_OOP_

    14. **Java高级特性**:涵盖反射、注解、动态代理、模块化系统(Jigsaw)等Java的进阶特性。 课程资料“Programmation Orientée Objet en Java SMI S5 2020-2021.pdf”将详细讲解以上知识点,并通过实例解析和练习...

    JAVA_sample_150.rar_JavaPOS_Sample.zi_java samp_java sample

    这些样本涵盖了从基础语法到高级特性的各种实例,包括但不限于类、对象、数据类型、控制结构、异常处理、IO流、多线程、网络编程、集合框架、反射、注解、设计模式等内容。 在"JAVA编程150例"这个压缩包文件中,每...

    demo-反射项目源码.rar_DEMO_java 反射_pulls87_算法

    在“demo-反射项目源码.rar_DEMO_java 反射_pulls87_算法”这个压缩包中,我们可以期待找到一个关于Java反射的实际应用示例,可能是用于演示如何在代码中动态地获取和操作类的信息。这里,"pulls87"可能是指该项目的...

    java注解_反射_字节码_类加载机制.zip

    Java反射允许程序在运行时动态地获取类的信息并操作类的对象。它能获取类的结构(如类名、字段、方法),创建对象,调用方法,访问私有成员。反射是许多框架(如Spring、Hibernate)的基础,用于实现动态代理、元...

    JDBC_Java反射技术入门

    在这个“JDBC_Java反射技术入门”资源中,初学者可以了解到如何使用Java进行数据库操作的基础知识,包括连接数据库、执行SQL语句、处理查询结果等。 1. **JDBC基础**: - **加载驱动**:在使用JDBC之前,我们需要...

    Java_api.rar_java API_java api

    8. **反射机制**:`java.lang.reflect`包提供了反射API,允许程序在运行时动态地获取类的信息并操作类的对象。 9. **国际化和本地化**:`java.text`和`java.util.Locale`支持不同地区和语言的本地化处理。 10. **...

    Java_Spring反射

    反射是Java语言的一个强大特性,允许程序在运行时检查类的信息,如类名、方法、属性等,并能动态创建和操作对象。在Spring框架中,反射被用来实现以下几个核心功能: 1. **依赖注入(DI)**:Spring通过反射机制...

Global site tag (gtag.js) - Google Analytics