黑马程序员——反射

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------


  什么时反射,根据个人理解,就是通过一个类的字节码获取和使用这个类里面的方法、字段、构造方法等。

  所以反射,首先是要获得类的字节码。其中获取字节码的方法有3种:

  1.使用Class类的forName(String className)静态方法,className表示全限定名;如String的全限定名:java.lang.String。

  2.调用某个对象的getClass()方法。该方法属于Object类。如Class<?> clz=new String().getClass。

  3.调用某个类的class属性获取Class对象,如Date.class会返回Date类对应的Class对象(其实就是得到一个类的一份字节码文件);

  接下来就是如何通过一个类的字节码获取和使用这个类里面的方法、字段、构造器。这就要涉及到java里提供的类:Constructor类、Method、Field、Annotation等类。

  先说Constructor类,Constructor类用于描述类中的构造方法。

  Class类中用于处理Constructor类的方法:

  Constructor<T> getConstructor(Class<?>... parameterTypes);返回该Class对象表示类的指定的public构造方法; 

  Constructor<?>[] getConstructors();返回该Class对象表示类的所有public构造方法; 

  Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes);返回该Class对象表示类的指定的构造方法,和访问权限无关;

  Constructor<?>[] getDeclaredConstructors();返回该Class对象表示类的所有构造方法,和访问权限无关;

  newInstance();利用构造方法创建对象。(该方法属于Constructor类)

  例子代码如下:

package bokedemo;
 
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
 
public class ReflectDemo {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class<ConstrutorDemo> clz=ConstrutorDemo.class;
//获取参数为int的构造器
Constructor<ConstrutorDemo> constructor=clz.getConstructor(int.class);
System.out.println(constructor);
//获取public修饰的构造方法
Constructor<?>[] constructors=clz.getConstructors();
for (Constructor<?> constructor2 : constructors) {
System.out.println(constructor2);
}
//获取参数String被private修饰的构造方法
Constructor<ConstrutorDemo> constructorprivate=clz.getDeclaredConstructor(String.class);
System.out.println(constructorprivate);
//获取所有构造方法包括private修饰的构造方法
Constructor<?>[] constructorsall=clz.getDeclaredConstructors();
for (Constructor<?> constructor2 : constructorsall) {
System.out.println(constructor2);
}
//设置使用时不检查该构造方法是否为私有
constructorprivate.setAccessible(true);
//利用获得的Constructor对象获得相应类的对象
ConstrutorDemo cdemo=constructorprivate.newInstance("hao");
}
}
class ConstrutorDemo
{
public ConstrutorDemo(){
System.out.println("public no param");
}
public ConstrutorDemo(int i){
System.out.println("public has param");
}
private ConstrutorDemo(String str){
System.out.println("private has param");
}
}

  接着是Method类,Method类用于描述类中的方法。

  Class类中用于Method类的方法有:

  Method getMethod(String name, Class<?> ... parameterTypes):返回该Class对象表示类和其父类的指定的public方法; 

  Method[] getMethods():返回该Class对象表示类和其父类的所有public方法; 

  Method getDeclaredMethod(String name, Class<?>... parameterTypes):返回该Class对象表示类的指定的方法。和访问权限无关,但不包括继承的方法;

  Method[] getDeclaredMethods(): 获得类所有的方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法;

  invoke(Object obj,Object ... args):obj表示调用底层方法的对象,后面的args表示传递的实际参数。如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可

以为 如果底层方法所需的形参个数为 0,则所提供的 args 数组长度可以为 0 或 null(不写,null,或 new Object[]{})。(该方法属于Method)

  例子代码如下:

package bokedemo;
 
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
public class ReflectDemo {
public static void main(String[] args) throws Exception{
//获取字节码
Class<?> clz=MethodDemo.class;
MethodDemo mdemo=(MethodDemo) clz.newInstance();
//通过反射获得参数为int和String的public修饰的名为methodpublic的方法。
Method method=clz.getMethod("methodpublic", new Class<?>[]{int.class,String.class});
//通过反射调用参数为int和String的public修饰的名为methodpublic的方法。
method.invoke(mdemo, new Object[]{1,"hao"});
//通过反射获取所有的public修饰的方法包括从父类继承的public方法。 
Method[] methods=clz.getMethods();
for (Method method2 : methods) {
System.out.println(method2);
}
//通过反射获得参数为int被private修饰的名为methodprivate的方法。
Method methodprivate=clz.getDeclaredMethod("methodprivate", int.class);
//设置使调用时不被检查
methodprivate.setAccessible(true);
//通过反射调用参数为int被private修饰的名为methodprivate的方法。
methodprivate.invoke(mdemo, new Object[]{1});
// 获得类所有的方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法;
Method[] methodall=clz.getDeclaredMethods();
for (Method method2 : methodall) {
System.out.println(method2);
}
}
}
class MethodDemo
{
public void methodpublic()
{
System.out.println("methodpublic1 no param");
}
public void methodpublic(int i)
{
System.out.println("methodpublic1 has one param int");
}
public void methodpublic(int i,String str)
{
System.out.println("methodpublic1 has two param int and string");
}
private void methodprivate()
{
System.out.println("methodprivate no param");
}
private void methodprivate(int i)
{
System.out.println("methodprivate has one param int");
}
private void methodprivate(int i,String str)
{
System.out.println("methodprivate has two param int and string");
}
}

  然后是Field类,Field类用于描述类中的字段。

  Class类中用于处理Field类的主要方法:

  Field getField(String name) :返回该Class对象表示类和其父类的指定的public字段;  

  Field[] getFields() :返回该Class对象表示类和其父类的所有public字段;

  Field getDeclaredField(String name):返回该Class对象表示类的指定的字段和访问权限无关,但不包括继承的字段; 

  Field[] getDeclaredFields():返回当前Class对象中公共、保护、默认(包)访问和私有字段,但不包括继承的字段;

  get(Object object):返回指定字段的值。(该方法属于Field)

  Setxxx(Object obj,xxx val):将obj对象的该Field字段设置成val值,此处的xxx表示8个基本数据类型。若该字段的类型是引用数据类型则使用,void set(Object obj, Object value);(该方法属于Field)

  最后是Annotation类,Annotation类用于描述类中的注释。

  Class类中用于处理Annotation类的主要方法:

  <A extends Annotation> A  getAnnotation(Class<A> annotationClass):如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null; 

 Annotation[] getAnnotations():返回此元素上存在的所有注释; 

 Annotation[] getDeclaredAnnotations():返回直接存在于此元素上的所有注释;

boolean isAnnotationPresent(Class<? extends Annotation> clz) :如果clz注释存在于此元素上,则返回 true,否则返回 false ; 

 

 

 

 


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值