`

Java之反射详解

阅读更多
反射API在java是非常强大和有用的, 比如现在流行的框架Spring, Hibernate, Junit 等等这些J2EE框架中都有大量使用,而且是作为核心功能!先来了解一下反射的用处,本文中会结合实例一起来实战练习这些API的使用
反射机制是java一直在进步的原因之一,它可以:
1、在应用程序运行时查看和修改程序的行为
2、可以查看类、接口、枚举、得到类的内部结构、方法和运行时的信息
3、通过反射来实例化他的对象来改变字段的值和调用方法执行
==================================华丽的分割线==================================
目录:
1、前言
2、类的反射

  • 获取类对象
  • 获取超类
  • 获取类的公共成员
  • 获取声明的类
  • 获取声明的当前类
  • 获取包名
  • 获取类的修饰符
  • 获取类的参数类型
  • 获取实现类的接口
  • 获取所有的公共方法
  • 获取类所有的公共构造函数
  • 获取所有的公共字段
  • 获取所有的注解

3、字段的反射
  • 获取公共字段
  • 获取当前字段所在类
  • 获取字段类型
  • Set/Get公共字段
  • Set/Get私有字段

4、方法的反射
  • 获取公共方法
  • 调用公共方法
  • 调用私有方法

5、构造函数反射
  • 获取公共方法的构造函数
  • 通过构造函数实例化对象

==================================华丽的分割线==================================
一、前言
我们正常的程序就不用使用发射了,因为对象啥都有了! 我这里要提的是反射在访问类和接口时的一些弊端:
1、性能:由于是动态的去解析类型,要先去查找类路径和加载类信息导致性能下降
2、安全问题:由于反射是可以访问类的所有方法,当有一些私有的方法被访问到,就存在了一定的风险了;会出现异常!
3、维护难:反射的代码一般都比较难维护和调试
二、类的反射
在Java中每个对象都可以是基本类型或者引用, 类、接口、数组、枚举等的引用都继承自Object对象,基本类型:【int chart double boolean byte short float long】

对于反射操作, java.lang.class是他的入口点, JVM为每一个对象类型都保存了一个不可变的对象实例, 该实例提供一些方法来检查对象的属性和创建新的方法, 还可以调用方法去修改属性字段值等

为了验证这些我先创建一个类继承接口的多层次结构类
BaseInterface.java 
package com.gyj.reflection;

public interface BaseInterface {
	public int interFaceInt = 0;
	
	void method1();
	
	int method2(String str);
}


BaseClass.java
package com.gyj.reflection;

public class BaseClass {

	private int baseInt;
	
	private static void method3() {
		System.out.println("method3");
	}
	
	private int method4() {
		System.out.println("method4");
		return 0;
	}
	
	public static void method5() {
		System.out.println("method5");
	}

	void method6() {
		System.out.println("method6");
	}
	
	//内部类
	public class BaseClassInnerClass{}
	
	//枚举
	public enum BaseClassMemberEnum{}
}

Concrete.java
package com.gyj.reflection;



import javax.annotation.Resource;

@Resource
public class Concrete extends BaseClass implements BaseInterface{
	public int publicInt;
	private String privateString = "private string";
	protected boolean protectedBoolean;
	Object defaultObject;
	
	public Concrete(int i) {
		this.publicInt = i;
	}
	
	/**
	 * @param args
	 * @throws ClassNotFoundException 
	 */
	public static void main(String[] args) throws ClassNotFoundException {
		
		
	}

	@Override
	public void method1() {
		System.out.println("method1 impl");
	}

	@Override
	public int method2(String str) {
		System.out.println("method2 impl");
		return 0;
	}
	
	public int method4() {
		System.out.println("重写 method4 ");
		return 0;
	}
	
	public int method5(int i) {
		System.out.println("重写 method4 ");
		return 0;
	}
	
	// 内部类
	public class ConcreteClassPublicClass{}
	private class ConcreteClassPrivateClass{}
	protected class ConcreteClassProtectedClass{}
	class ConcreteClassDefualtClass{}
	
	// 枚举
	enum ConcreteClassDefultEnum{}
	public enum ConcreteClassPublicEnum{}
	
	// 接口
    public interface ConcreteClassPublicInterface{}

    
    
    
    
    
    
    
	public int getPublicInt() {
		return publicInt;
	}

	public void setPublicInt(int publicInt) {
		this.publicInt = publicInt;
	}

	public String getPrivateString() {
		return privateString;
	}

	public void setPrivateString(String privateString) {
		this.privateString = privateString;
	}
    
    
}



=============================================================================================================================================
  • 获取类对象
  •    通常获取类的对象有三种方法,一种是直接使用类的静态变量, 一种是对象的.class()
       还有就是java.lang.class.forName方法,对于基本数据类型我们用类的静态变量,具体看demo实例;
    Class<?> concreteClass = Concrete.class.getClass();
    concreteClass = new Concrete(5).getClass();
    try {
    	concreteClass = Class.forName("com.gyj.reflection.Concrete");
       } catch (ClassNotFoundException e) {
    	e.printStackTrace();
    }
    System.out.println(concreteClass.getCanonicalName());
    //============对于基本类型、包装类、数组===========
    Class<?> booleanClass = boolean.class;
    System.out.println(booleanClass.getCanonicalName());
    		
    Class<?> cDouble = Double.TYPE;
    System.out.println(cDouble.getCanonicalName());
    		
    Class<?> cDoubleArray = Class.forName("[D");
    System.out.println(cDoubleArray.getCanonicalName());
    		
    Class<?> twoDStringArray = String[][].class;
    System.out.println(twoDStringArray.getCanonicalName());
    		
    //out put========================
    com.gyj.reflection.Concrete
    boolean
    double
    double[]
    java.lang.String[][]
    

  • 获取超类
  • getSuperclass()方法返回当前类的超类,如果当前类是object 则返回null 数组、接口返回Object 类

    Class<?> superClass = Class.forName("com.gyj.reflection.Concrete").getSuperclass();
    System.out.println("===========得到超类==========");
    System.out.println(superClass);
    System.out.println(Object.class.getSuperclass());
    System.out.println(String[][].class.getSuperclass());
    
    out put===========
    class com.gyj.reflection.BaseClass
    null
    class java.lang.Object
    

  • 获取类的公共成员
  • getClasse()方法返回一个类中所有公共类、接口、枚举的数组,包括了从父类中继承过来的,如果没有则返回长度为0的数组

    Class<?>[] classes = Concrete.class.getClasses();
    System.out.println(Arrays.toString(classes));
    
    //out put=================
    [class com.gyj.reflection.Concrete$ConcreteClassPublicClass, 
    class com.gyj.reflection.Concrete$ConcreteClassPublicEnum,
    interface com.gyj.reflection.Concrete$ConcreteClassPublicInterface,
    class com.gyj.reflection.BaseClass$BaseClassInnerClass, 
    class com.gyj.reflection.BaseClass$BaseClassMemberEnum]
    
  • 获取全部声明的类
  • getDeclaredClasses() 方法返回当前Class类中声明的类,包括继承和接口的类
    Class<?>[] explicitClasses = Class.forName("com.gyj.reflection.Concrete").getDeclaredClasses();
    System.out.println(Arrays.toString(explicitClasses));
    
    //out put================
    [class com.gyj.reflection.Concrete$ConcreteClassDefualtClass, 
    class com.gyj.reflection.Concrete$ConcreteClassDefultEnum, 
    class com.gyj.reflection.Concrete$ConcreteClassPrivateClass, 
    class com.gyj.reflection.Concrete$ConcreteClassProtectedClass, 
    class com.gyj.reflection.Concrete$ConcreteClassPublicClass, 
    class com.gyj.reflection.Concrete$ConcreteClassPublicEnum, 
    interface com.gyj.reflection.Concrete$ConcreteClassPublicInterface]
    
    


  • 获取当前声明的类
  • getDeclaringClass()方法返回一个当前被其声明的类成员对象

    Class<?> innerClass = Class.forName("com.gyj.reflection.Concrete$ConcreteClassPublicInterface");
    System.out.println(innerClass.getEnclosingClass().getCanonicalName());
    System.out.println(innerClass.getDeclaringClass().getCanonicalName());
    
    //out put================
    com.gyj.reflection.Concrete
    com.gyj.reflection.Concrete
    

  • 获取包名
  • System.out.println(Class.forName("com.gyj.reflection.Concrete").getPackage().getName());
    out put================
    com.gyj.reflection


  • 获取类的修饰符
  • System.out.println(Modifier.toString(Concrete.class.getModifiers()));
    System.out.println(Modifier.toString(Class.forName("com.gyj.reflection.Concrete").getModifiers()));
    System.out.println((Modifier.toString(Concrete.class.getModifiers())).equals(Modifier.toString(Class.forName("com.gyj.reflection.Concrete").getModifiers())));
    
    //out put================
    public
    public
    true


  • 获取类的参数类型
  • 就以HashMap为例子,大家知道他的参数类型是‘K V’
    TypeVariable<?>[] typeVariables = Class.forName("java.util.HashMap").getTypeParameters();
    for (TypeVariable<?> typeVariable : typeVariables) {
    	System.out.println(typeVariable.getName() + ",");
    }
    
    //out put===============
    K,
    V,
    


  • 获取实现类的接口
  • System.out.println(Arrays.toString(Class.forName("java.util.HashMap").getInterfaces()));
    
    //out put===============
    [interface java.util.Map, interface java.lang.Cloneable, interface java.io.Serializable]
    

  • 获取所有的公共方法
  • getMethods()返回的是包括该类以及他的父类和接口所有的公共方法的数组集合

    Method[] publicMethods = Class.forName("com.gyj.reflection.Concrete").getMethods();
    System.out.println("=========类的公共方法==========");
    System.out.println(Arrays.toString(publicMethods));
    
    //out put==============
    [public static void com.gyj.reflection.Concrete.main(java.lang.String[]) throws java.lang.ClassNotFoundException, public java.lang.String com.gyj.reflection.Concrete.getPrivateString(), 
    public void com.gyj.reflection.Concrete.setPrivateString(java.lang.String), 
    public void com.gyj.reflection.Concrete.method1(), 
    public int com.gyj.reflection.Concrete.method2(java.lang.String), 
    public int com.gyj.reflection.Concrete.method4(), 
    public int com.gyj.reflection.Concrete.method5(int), 
    public int com.gyj.reflection.Concrete.getPublicInt(), 
    public void com.gyj.reflection.Concrete.setPublicInt(int), 
    public static void com.gyj.reflection.BaseClass.method5(),
    public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException,
    public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException,
    public final void java.lang.Object.wait() throws java.lang.InterruptedException, 
    public boolean java.lang.Object.equals(java.lang.Object), 
    public java.lang.String java.lang.Object.toString(), 
    public native int java.lang.Object.hashCode(), 
    public final native java.lang.Class java.lang.Object.getClass(), 
    public final native void java.lang.Object.notify(), 
    public final native void java.lang.Object.notifyAll()]
    
    //ps:大家可以数数看是不是有这么多,自己试试!
    


  • 获取类所有的公共构造函数
  • Constructor<?>[] publicConstructors = Class.forName("com.gyj.reflection.Concrete").getConstructors();
    System.out.println(Arrays.toString(publicConstructors));
    
    //out put==============
    [public com.gyj.reflection.Concrete(int)]
    

  • 获取所有的公共字段
  • getFields()得到包括接口以及父类的所有公共字段

    Field[] publicField = Class.forName("com.gyj.reflection.Concrete").getFields();
    System.out.println(Arrays.toString(publicField));
    
    //out put==============
    [public int com.gyj.reflection.Concrete.publicInt,
     public static final int com.gyj.reflection.BaseInterface.interFaceInt]
    



  • 获取所有的注解
  • Annotation[] annotations = Class.forName("com.gyj.reflection.Concrete").getAnnotations();
    System.out.println(Arrays.toString(annotations));
    
    //out put==============
    [@javax.annotation.Resource(shareable=true, mappedName=, description=, name=, type=class java.lang.Object, authenticationType=CONTAINER, lookup=)]
    


    三、字段的反射
  • 获取公共字段
  • try {
    	Field field = Class.forName("com.gyj.reflection.Concrete").getField("interFaceInt");
    	System.out.println(field.getName());
    } catch (NoSuchFieldException e) {
    	e.printStackTrace();
    } catch (SecurityException e) {
    	e.printStackTrace();
    }
    
    //out put============
    interFaceInt
    

  • 获取当前字段所在类
  • try {
    	Field field = Class.forName("com.gyj.reflection.Concrete").getField("interFaceInt");
    	Class<?> fieldClass = field.getDeclaringClass();
    	System.out.println(fieldClass.getCanonicalName());
    } catch (NoSuchFieldException e) {
    	e.printStackTrace();
    } catch (SecurityException e) {
    	e.printStackTrace();
    }
    
    //out put============
    com.gyj.reflection.BaseInterface
    

  • 获取字段类型
  • try {
    	Field field = Class.forName("com.gyj.reflection.Concrete").getField("interFaceInt");
    	Class<?> fieldClass = field.getType();
    	System.out.println(fieldClass.getCanonicalName());
    } catch (NoSuchFieldException e) {
    	e.printStackTrace();
    } catch (SecurityException e) {
    	e.printStackTrace();
    }
    
    //out put=============
    int
    

  • Set/Get公共字段
  • try {
    	Field field = Class.forName("com.gyj.reflection.Concrete").getField("publicInt");
    	Concrete obj = new Concrete(5);
    	try {
    		Object o = field.get(obj);
    		System.out.println("字段值 = " + o);
    		field.setInt(obj, 10);
    		System.out.println("字段值 = " + field.get(obj));
    	} catch (IllegalArgumentException | IllegalAccessException e) {
    		e.printStackTrace();
    	}
    } catch (NoSuchFieldException | SecurityException e) {
    	e.printStackTrace();
    }
    //out put===============
    字段值 = 5
    字段值 = 10
    //get()  方法返回的是一个对象,如果字段是基本类型则返回他的基本包装类。
    //设置值的时候,如果该字段是final类型则会抛异常java.lang.IllegalAccessException
    


  • Set/Get私有字段
  • try {
    	Field privateField = Class.forName("com.gyj.reflection.Concrete").getDeclaredField("privateString");
    	privateField.setAccessible(true);
    	Concrete concrete = new Concrete(12);
    	try {
    		System.out.println(privateField.get(concrete));
    		privateField.set(concrete, "update string");
    		System.out.println(privateField.get(concrete));
    	} catch (IllegalArgumentException | IllegalAccessException e) {
    		e.printStackTrace();
    	}
    } catch (NoSuchFieldException | SecurityException e) {
    	e.printStackTrace();
    }
    
    //out put==============
    private string
    update string
    
    


    四、方法的反射
  • 获取公共方法
  • getMethod()获取类的公共方法,其中参数形式为(方法名,参数类型) 如果在当前类中没有找到相应的方法,则会在父类中需找;

    try {
    	Method method = Class.forName("java.util.HashMap").getMethod("put", Object.class, Object.class);
    	System.out.println("===========HashMap 方法的参数类型是============");
    	System.out.println("方法参数类型 " + Arrays.toString(method.getParameterTypes()));
    	System.out.println("方法返回类型 " + method.getReturnType());
    	System.out.println("方法修饰类型 " + Modifier.toString(method.getModifiers()));
    } catch (NoSuchMethodException | SecurityException e) {
    	e.printStackTrace();
    }
    
    //out put=============
    方法参数类型 [class java.lang.Object, class java.lang.Object]
    方法返回类型 class java.lang.Object
    方法修饰类型 public
    

  • 调用公共方法
  • try {
    	Method method = Class.forName("java.util.HashMap").getMethod("put", Object.class, Object.class);
    	Map<String, Object> map = new HashMap<String, Object>();
    	try {
    		method.invoke(map, "key", "value");
    		System.out.println("===========调用公共方法===========");
    		System.out.println("map = " + map);
    	} catch (IllegalAccessException | IllegalArgumentException
    			| InvocationTargetException e) {
    		e.printStackTrace();
    	}
    } catch (NoSuchMethodException | SecurityException e) {
    	e.printStackTrace();
    }
    
    //out put==============
    map = {key=value}
    //如果方法是静态的,则把参数传递为NULL
    


  • 调用私有方法
  • try {
    	Method method;
    	try {
    		method = Class.forName("com.gyj.reflection.BaseClass").getDeclaredMethod("method3", null);
    		method.setAccessible(true);
    		System.out.println("===========调用静态私有方法===========");
    		method.invoke(null, null);
    	} catch (NoSuchMethodException | SecurityException e) {
    		e.printStackTrace();
    	}
    } catch (IllegalAccessException | IllegalArgumentException
    		| InvocationTargetException e) {
    	e.printStackTrace();
    }
    
    //out put==============
    ===========调用静态私有方法===========
    method3
    
    


    五、构造函数反射
  • 获取公共方法的构造函数
  • getConstructor() 方法来得到对象类具体的公共构造函数方法,并且可以获取到对象之后在创建类的实例;

    try {
    	Constructor<?> constructor = Class.forName("com.gyj.reflection.Concrete").getConstructor(int.class);
    	System.out.println(Arrays.toString(constructor.getParameterTypes()));
    	
    	Constructor<?> hashMapConstructor = Class.forName("java.util.HashMap").getConstructor(null);
    	System.out.println(Arrays.toString(hashMapConstructor.getParameterTypes()));
    } catch (NoSuchMethodException | SecurityException e) {
    	e.printStackTrace();
    }
    
    //out put===============
    [int]
    []
    


  • 通过构造函数实例化对象
  • newInstance()方法得到一个类的实例,然后就可以去调用方法或访问字段的值

    try {
    	Constructor<?> constructor = Class.forName("com.gyj.reflection.Concrete").getConstructor(int.class);
    	System.out.println(Arrays.toString(constructor.getParameterTypes()));
    	Object myObject;
    	try {
    		myObject = constructor.newInstance(12);
    		Method method = myObject.getClass().getMethod("method1", null);
    		method.invoke(myObject, null);
    	} catch (InstantiationException | IllegalAccessException
    			| IllegalArgumentException | InvocationTargetException e) {
    		e.printStackTrace();
    	}
    } catch (NoSuchMethodException | SecurityException e) {
    	e.printStackTrace();
    } 
    
    try {
    	Constructor<?> hashMapConstructor = Class.forName("java.util.HashMap").getConstructor(null);
    	System.out.println(Arrays.toString(hashMapConstructor.getParameterTypes()));
    	Map<String, Object> map = (Map<String, Object>) hashMapConstructor.newInstance(null);
    	map.put("key", "value");
    	System.out.println(map);
    } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
    	e.printStackTrace();
    }
    
    
    //out put================
    [int]
    method1 impl
    []
    {key=value}
    

    ================================================================完毕==================================================================
    分享到:
    评论
    2 楼 坏我一锅粥 2014-03-23  
    cystudent 写道
      大表哥牛逼!

    你?
    1 楼 cystudent 2014-03-23  
      大表哥牛逼!

    相关推荐

      java 反射机制详解

      Java 反射机制是 Java 语言中的一个重要特性,它允许程序在运行时动态地获取类的信息(如类名、属性、方法等)并调用对象的方法,甚至修改对象的状态。这一机制极大地增强了 Java 程序的灵活性和可扩展性,尤其是在...

      JAVA反射机制详解视频

      (通过反射获取无参构造方法并使用) (通过反射获取带参构造方法并使用) (通过反射获取私有构造方法并使用) (通过反射获取成员变量并使用) (通过反射获取无参无返回值成员方法并使用) (通过反射获取带参带返回值成员...

      java反射机制详解

      ### Java反射机制详解 #### 一、反射机制是什么 反射机制是Java编程语言的一个核心特性,它允许程序在运行时动态地获取类的信息,并且能够动态地创建对象和调用对象的方法。简单来说,反射机制使得Java程序可以...

      java反射详解

      ### Java反射机制详解 #### 一、引言 Java反射机制是Java编程语言的一个核心特性,它允许程序在运行时动态地访问类的信息,并能够直接操作这些类的对象。这种能力对于许多开发框架(如Spring)来说至关重要,因为...

      java反射原理详解

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

      java反射机制详解与应用

      Java反射机制是Java语言的一项强大功能,它允许程序在运行时动态地获取类的信息并操作类的对象。这一特性使得Java具有高度的灵活性和强大的扩展性,尤其是在开发框架和库时,反射机制起到了至关重要的作用。本文将...

      JAVA 反射详解PPT

      Java反射机制是Java编程语言中的一个重要特性,它允许程序在运行时检查和操作类、接口、对象等的内部信息。通过反射,我们可以动态地创建对象、访问和修改字段、调用方法,甚至执行私有方法和访问包内可见的元素。...

      JAVA反射详解

      ### JAVA反射详解 Java反射是Java编程语言的一个强大特性,允许程序在运行时检查和操作类、接口、字段和方法等。本文章旨在深入解析Java反射机制,包括其原理、应用以及常见用法。 #### 了解Class对象 在Java中,...

      Java Reflection (JAVA反射)详解

      以下是对Java反射机制的详细解释: 1. 获取类信息: 要使用反射,首先需要获取类的`java.lang.Class`对象。这可以通过以下几种方式实现: - `Class&lt;?&gt; c = Class.forName("全限定类名");`:根据类的全限定名(包...

      java反射详解例子

      "java反射机制详解" Java 反射机制是 Java 语言中的一种功能,它允许程序员在运行时检查和修改一个类的结构和行为。 Java 反射机制提供了一种获取类的信息、创建对象、调用方法和获取字段值的方式。 在 Java 中,...

      Java反射详解.pdf

      反射机制是Java编程的强大工具之一,但它也带来了安全性和性能问题,因此需要谨慎使用。在Java中,反射主要是通过java.lang.reflect包下的Class类来实现的。 在上述内容中,首先介绍了通过反射获取类的信息的基本...

      JAVA基础--JAVA中的反射机制详解

      JAVA 反射机制详解 JAVA 反射机制是 Java 语言中的一种动态获取信息和动态调用对象方法的功能。它允许程序在运行时获取类的信息、构造对象、获取成员变量和方法、调用对象的方法等。 Java 反射机制主要提供了以下...

      JAVA反射机制详解

      ### JAVA反射机制详解 #### 一、JAVA反射机制概述 反射是Java编程语言的一个核心特性,它允许程序在运行时获取类的信息,并且可以动态地创建对象和调用方法。这种能力使得Java程序具备了高度的灵活性和扩展性。...

      Java 反射详解

      Java反射是Java编程语言中的一个强大特性,它允许运行时的程序访问并操作类、接口、字段和方法等对象,即使这些对象在编译时并未被明确地引用。这一特性使得Java具有高度的动态性,使得代码能够在运行时检查类的信息...

      java反射机制详解与应用.pdf

      Java 反射机制详解与应用 Java 反射机制是一种非常强大的动态相关机制,允许 Java 程序在运行时加载、探知、使用编译期间完全未知的类别。这种机制允许程序在运行时透过 Reflection APIs 取得任何一个已知名称的...

    Global site tag (gtag.js) - Google Analytics