黑马程序员——Java基础之反射

-----------android培训java培训、java学习型技术博客、期待与您交流!------------


Java基础之反射

1.什么反射机制,反射机制的作用:

        简单的来说,反射机制指的是程序在运行时能够获取自身的信息。只要给 定类的名字,就可以通过反射机制来获得类的所有信息,并调用类的方法。

       要了解反射机制的作用就涉及到了动态与静态的概念:

静态编译:在编译时确定类型,绑定对象。

动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。

       反射机制的作用就是可以实现动态创建对象和编译,体现出很大的灵活性,基于这个特性为设计的程序框架有极大的灵活性(java程序框架中大量用到此特性)。

2.反射机制实现原理:

       jdk在运行时可以将每个类封装成一个叫“Class”的类,此类是对运行的类进行描述与封装的类,是反射机制运用的基石,通过这个类我们可以得到任何类的内部结构(字段、方法、注解甚至是修饰关键字),进而调用这个为原方法,利用这个类的相关属性等等。也就是说通过这个机制程序在设计时可以不指定具体的需要运行的类,在实际运行的时候才确定具体的类,都可以运行。

3.反射机制的基石:Class类

       此类是反射机制的基石(可以把它看成一个普通的类就好理解了),通过这个类可以得到任意一个类的信息,获得Class对象的方式主要有三种:

1、调用某个类的class性获取Class对象,如Person.class会返回Person类对应的Class 对象;

2、使用Class的forName(StringclassName)静态方法,className表示全限定名;

3、调用某个对象的getClass()方法。该方法属于Object类;

**********************************************************************

//方式一

       Class c1 = Person.class;

       //方式二(最为常用,最好用)

       Class c2 = Class.forName("com.chenpj.reflection.Person");

       //方式三

       Class c3 = newPerson().getClass();

       System.out.println(c1);

       System.out.println(c2);

       System.out.println(c3);

**********************************************************************

4.常用方法:

方法摘要

<AextendsAnnotation>
A

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

Annotation[]

getAnnotations()
返回此元素上存在的所有注释。

ClassLoader

getClassLoader()
返回该类的类加载器。

Constructor<T>

getConstructor(Class...parameterTypes)
返回一个Constructor对象,它反映此Class对象所表示的类的指定公共构造方法。

Constructor[]

getConstructors()
返回一个包含某些Constructor对象的数组,这些对象反映此Class对象所表示的类的所有公共构造方法

Annotation[]

getDeclaredAnnotations()
返回直接存在于此元素上的所有注释。

Class[]

getDeclaredClasses()
返回Class对象的一个数组,这些对象反映声明为此Class对象所表示的类的成员的所有类和接口,包括该类所声明的公共、保护、默认(包)访问及私有类和接口,但不包括继承的类和接口。

Constructor<T>

getDeclaredConstructor(Class...parameterTypes)
返回一个Constructor对象,该对象反映此Class对象所表示的类或接口的指定构造方法

Constructor[]

getDeclaredConstructors()
返回Constructor对象的一个数组,这些对象反映此Class对象表示的类声明的所有构造方法

Field

getDeclaredField(Stringname)
返回一个Field对象,该对象反映此Class对象所表示的类或接口的指定已声明字段。

Field[]

getDeclaredFields()
返回Field对象的一个数组,这些对象反映此Class对象所表示的类或接口所声明的所有字段,包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段。

Method

getDeclaredMethod(Stringname,Class...parameterTypes)
返回一个Method对象,该对象反映此Class对象所表示的类或接口的指定已声明方法。

Method[]

getDeclaredMethods()
返回Method对象的一个数组,这些对象反映此Class对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。

Class<?>

getDeclaringClass()
如果此Class对象所表示的类或接口是另一个类的成员,则返回的Class对象表示该对象的声明类。

T[]

getEnumConstants()
如果此Class对象不表示枚举类型,则返回枚举类的元素或null。

Field

getField(Stringname)
返回一个Field对象,它反映此Class对象所表示的类或接口的指定公共成员字段

Field[]

getFields()
返回一个包含某些Field对象的数组,这些对象反映此Class对象所表示的类或接口的所有可访问公共字段

Type[]

getGenericInterfaces()
返回表示某些接口的Type,这些接口由此对象所表示的类或接口直接实现。

Type

getGenericSuperclass()
返回表示此Class所表示的实体(类、接口、基本类型或void)的直接超类的Type

Class[]

getInterfaces()
确定此对象所表示的类或接口实现的接口。

Method

getMethod(Stringname,Class...parameterTypes)
返回一个Method对象,它反映此Class对象所表示的类或接口的指定公共成员方法。

Method[]

getMethods()
返回一个包含某些Method对象的数组,这些对象反映此Class对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共member方法

int

getModifiers()
返回此类或接口以整数编码的Java语言修饰符。

String

getName()
String的形式返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称。

Package

getPackage()
获取此类的包。

ProtectionDomain

getProtectionDomain()
返回该类的ProtectionDomain

Class<?superT>

getSuperclass()
返回表示此Class所表示的实体(类、接口、基本类型或void)的超类的Class

TypeVariable<Class<T>>[]

getTypeParameters()
按声明顺序返回TypeVariable对象的一个数组,这些对象表示用此GenericDeclaration对象所表示的常规声明来声明的类型变量。

boolean

isAnnotation()
如果此Class对象表示一个注释类型则返回true。

boolean

isAnnotationPresent(Class<?extendsAnnotation>annotationClass)
如果指定类型的注释存在于此元素上,则返回true,否则返回false。

boolean

isAnonymousClass()
当且仅当基础类是匿名类时返回true

boolean

isArray()
判定此Class对象是否表示一个数组类。

boolean

isAssignableFrom(Class<?>cls)
判定此Class对象所表示的类或接口与指定的Class参数所表示的类或接口是否相同,或是否是其超类或超接口。

boolean

isEnum()
当且仅当该类声明为源代码中的枚举时返回true。

boolean

isInstance(Objectobj)
判定指定的Object是否与此Class所表示的对象赋值兼容。

boolean

isInterface()
判定指定的Class对象是否表示一个接口。

boolean

isLocalClass()
当且仅当基础类是本地类时返回true

boolean

isMemberClass()
当且仅当基础类是成员类时返回true

boolean

isPrimitive()
判定指定的Class对象是否表示一个基本类型。

boolean

isSynthetic()
如果此类是复合类,则返回true,否则false

T

newInstance()
创建此Class对象所表示的类的一个新实例。

 

例如:通过Class类得到某个对象的方法,字段以及构造器:

**********************************************************************

//得到Class对象

Classc2=Class.forName("com.chenpj.reflection.Person");

       //得到所有方法(包括私有方法)

       Method[]methods=c2.getDeclaredMethods();

       System.out.println("---------得到所有方法--------------");

       for(Method  method:methods){

           System.out.println("方法权限修饰:"

+Modifier.toString(method.getModifiers()));

method.setAccessible(true);//将方法设为可访问(包括私有的方法)

           System.out.println("方法名:"+method.getName());

System.out.println("方法返回类型:"+method.getReturnType());

System.out.println("方法参数类型:"+method.getParameterTypes());

           System.out.println("~~~~~~~~~~~~~~~~~~");

       }

       System.out.println("---------得到所有字段--------------");

       //得到所有字段

       Field[]fields=c2.getDeclaredFields();

       for(Field  field:fields){

           System.out.println(field);

       }

       System.out.println("---------得到所有造器--------------");

       //得到所有构造器(此方法不能得到私用构造方法,具体看API

       Constructor[]constructor=c2.getConstructors();

       for(Constructor  constructor2:constructor){

           System.out.println(constructor2);

       }

**********************************************************************

利用反射实例化对象:

方式一:通过默认的无参构造器;

方式二:通过指定的构造器,例如:

**********************************************************************

       Class c2=Class.forName("com.chenpj.reflection.Person");

       //方式一:通过默认构造方法:

       Personperson=(Person)c2.newInstance();

       person.eat("面条");

      

//方式二:通过指定的构造方法:

Constructorconstructor=c2.getConstructor(int.class,String.class,String.class);

Personperson=(Person)constructor.newInstance(20,"tom","USA");

       System.out.println(person);

**********************************************************************

使用反射调用方法

步骤:

1.通过类名得到Class;

2.通过Class的getMethod,getDeclaredMethod,得到指定的方法对应的Method类;

3.利用Method的invoke方法调用方法的执行,例如:

**********************************************************************

       Classc2=Class.forName("com.chenpj.reflection.Person");

       //一,访问public修饰方法

MethodeatMethod=c2.getMethod("eat",String.class);

eatMethod.invoke(c2.newInstance(),"面包");//方法调用需要传递一个对象及方法的参数

       //二、访问private修饰方法

Methodtest1Method=c2.getDeclaredMethod("test1",.class);

       test1Method.setAccessible(true);//设置方法可以访问

       test1Method.invoke(c2.newInstance(),"测试参数");

       //三,访问可变参数方法

Methodtest3Method=c2.getDeclaredMethod("test3",int[].class);

       test3Method.invoke(c2.newInstance(),newint[]{1});

**********************************************************************

默认情况下private修饰的方法是不可访问的,需要调用getDeclaredMethodstring,ags)方法得到,并调用Method对象的setAccessibleboolean)方法,传递”true”参数,将方法设置为可以访问。

使用反射给对象属性赋值:

第1步:通过类名得到Class

第2步:通过Class对象的getDeclaredFieldstring)方法得到指定的属性对应的Field类;

第3步:调用FieldsetAccessibleboolean),设置属性可以修改;

4步:通过Fieldset(obj,value)方法为属性赋值。

**********************************************************************

Classc2=Class.forName("com.chenpj.reflection.Person");

       //得到根据属性名得到对应的Field

       Fieldfield_name=c2.getDeclaredField("name");

       Fieldfield_aget=c2.getDeclaredField("age");

       //将属性设置为可设置

       field_name.setAccessible(true);

       field_aget.setAccessible(true);

       //得到一个属性所在的对象

       Objectobject=c2.newInstance();

       //高用set方法设置值

       field_name.set(object,"tomcat");

       field_aget.set(object,25);

 

        System.out.println(object);

**********************************************************************

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值