您的位置:首页 > 编程语言 > Java开发

DAY20--java中的反射机制常用知识点总结

2014-05-03 20:24 495 查看
1 首先是总结一下 什么叫做反射

反射:其实就是指动态的加载一个指定的类,并获取到该类中的所有内容。

并且将字节码封装成对象,并将字节码文件中的内容都封装成对象方便操作这些成员

反射技术可以对一个类进行解剖

2 优点:大大的增强了程序的扩展性

静态编译:在编译时确定类型,绑定对象即通过

动态编译:运行时确定类型,绑定对象。动态编译最大限度的发挥了java的灵活性,期限了多态的应用,

有利于降低类之间的耦合性。

反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,

特别是在J2EE的开发

它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么

并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。

3 反射的基本步骤:

1获得class对象 就是获取到指定的名称的字节码文件对象

2 实例化对象 获得类的属性 方法或构造函数

3 访问属性 调用构造函数创建对象

反射的引入:

Object obj =new Student();

1若编译和运行的类型都知道用instanceof 判断后 强转

2编译时无法判断该对象的类,程序只能依靠运行时的信息来发现对象真实信息,这时就必须使用反射了

3要是想得到对象真正的类型,就得使用反射。

反射就是得到元数据的行为;

用类来描述对象,类:描述数据的结构
用元数据来描述Class,MetaData(元数据):描述数据结构的结构;

获得类对象的3中方式:
1 调用某个类的class属性获得class对象,如Date.class会返回Date类对象的class对象
2使用Class类的forName(String className)静态方法,className表示全限定名;如String的权限定名:java.lang.String
3调用某个类对象的getClass()方法 该方法属于Object类
Class<?>pw=new Date().getClass();

获取class对象的方法

package com.itheima;

public class FanShe {
public static void main(String[] args) throws Exception {
//获得Class对象的方法(三种)
//一:调用属性
Class<String> c = String.class;
//打印结果:class java.lang.String  String.class就表示JVM中一份表示String类的字节码
System.out.println(c);

Class<String> c2 = String.class;
//true都是String类的字节码  		一个类在虚拟机中只有一份字节码;
System.out.println(c == c2);

//二:使用forName()方法

//Class cla = Class.forName("String");//ERROR,
Class<String> cla = (Class< String>)Class.forName("java.lang.String");//必须用上全限定名,否则报错
System.out.println(c == cla);//true

//三:利用对象调用Object的getClass方法;
Class<? extends String> c3 = new String().getClass();
System.out.println(c == c3);//ture
}
}


基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void通过class属性也表示为 Class 对象;

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

包装类和Void类的静态TYPE字段;

Integer.TYPE == int.class ;

Integer.class == int.class;

数组类型的Class实例对象:

Class<String[]> clz = String[].class;

数组的Class对象如何比较是否相等? 数组的维数和数组的类型;

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

预定义class对象之间的相互比较

package com.itheima;

public class classequals {
public static void main(String[] args) {

Class<?> in = int.class;
System.out.println(in);//int
Class<?> in2 = Integer.class;
//包装类都有一个常量TYPE,用来表示其基本数据类型的字节码
Class<?> in3 = Integer.TYPE;

System.out.println(in2);//class java.lang.Integer
System.out.println(in3);//int
System.out.println(in3 == in);//true 包装类都有一个常量TYPE,用来表示其基本数据类型的字节码,所以这里会相等!
System.out.println(in3 == in2);//false
Class<String[]> s = String [].class;
Class<int[]> i = int [].class;
//System.out.println(i ==s);//编译根本就通过不了,一个是int,一个是String
}
//这两个自定义的方法是可以的,一个int,一个Integer//包装类与基本数据类型的字节码是不一样的
public void show(int i){}
public void show(Integer i){}
}


利用class获取类的属性信息

package com.itheima;

import java.lang.reflect.Modifier;

class A {
}
interface B{
}
interface C{
}

public class GetClass extends A implements B,C{
//内部类
public class C{}
public interface D{}
public static void main(String[] args) {
//类可以,接口也可以
Class<GetClass> c = GetClass .class;
System.out.println(c);//class com.itheima.GetClass

//得到包名
System.out.println(c.getPackage());//package com.itheima

//得到全限定名
System.out.println(c.getName());//com.itheima.GetClass

//得到类的简称
System.out.println(c.getSimpleName());//GetClass

//得到父类
/**
* Class<? super T> getSuperclass() 此处super表示下限
返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。
*/
System.out.println(c.getSuperclass().getSimpleName());//A,先获取父类,再获取父类的简称

//得到接口
System.out.println(c.getInterfaces());//[Ljava.lang.Class;@1b60280
Class[] arr = c.getInterfaces();
for (Class cla : arr) {
System.out.println(cla);//interface com.itheima.B   interface com.itheima.C
}

//获得public修饰的类
/**
* Class<?>[] getClasses()
返回一个包含某些 Class 对象的数组,这些对象表示属于此 Class 对象所表示的类的成员的所有公共类和接口。 (如果内部类前面没有加上public的话那么得不到!)
*/
Class[] cl = c.getClasses();
System.out.println(cl.length);//在内部类没有加上public修饰的时候长度为0,加上就是2(获取的是公共的)
for (Class class1 : cl) {
System.out.println(class1);
}

//获得修饰符
int i = c.getModifiers();
System.out.println(i);//常量值1表示public
System.out.println(Modifier.toString(i));//直接打印出public
}
}


Class中得到构造方法 Constructor、方法Method、字段Filed

常用方法:

Constructor类用于描述类中的构造方法:

Constructor<T> getConstructor(Class<?>...parameterTypes)

返回该Class对象表示类的指定的public构造方法;

Constructor<?>[] getConstructors()

返回该Class对象表示类的所有public构造方法;

Constructor<T>getDeclaredConstructor(Class<?>... parameterTypes)

返回该Class对象表示类的指定的构造方法,和访问权限无关;

Constructor<?>[] getDeclaredConstructors()

返回该Class对象表示类的所有构造方法,和访问权限无关;

Method类用于描述类中的方法:

Method getMethod(String name,Class<?> ... parameterTypes)

返回该Class对象表示类和其父类的指定的public方法;

Method[] getMethods():

返回该Class对象表示类和其父类的所有public方法;

Method getDeclaredMethod(String name, Class<?>...parameterTypes)

返回该Class对象表示类的指定的方法。和访问权限无关,但不包括继承的方法;

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

使用constructor 实现暴力反射 并获得具体的类及对象

package com.itheima;

import java.lang.reflect.Constructor;

class Emp{
private String name;
private int age;
private Emp() {
}
Emp(String name){
}
public Emp(String name,int age){
}
}

public class ClassReture {
public static void main(String[] args) throws Exception {
//得到所有的构造器(先得到类)
Class<Emp> c = Emp.class;
/**
* Constructor<?>[] getConstructors()
返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。
*/
Constructor[] con = c.getConstructors();//前面的修饰符必须是public才可以在这个方法下获取到
for (Constructor cons : con) {
System.out.println("c.getConstructors()"+cons);//如果上面的某构造器public去掉,则显示不出
/**打印
public junereflect624.Emp(java.lang.String,int)
*/
}

//得到指定的构造器,也是必须public
Constructor c1 = c.getConstructor(String.class,int.class);
System.out.println(c1);//public com.itheima.Emp(java.lang.String,int)

System.out.println("====================================");
//现在想获得不受public影响的,getDeclaredConstructors(),暴力反射

con = c.getDeclaredConstructors();
for (Constructor cons : con) {

System.out.println("c.getDeclaredConstructors()=="+cons);//此时不受修饰符的影响
/**打印
====================================
c.getDeclaredConstructors()==private com.itheima.Emp()
c.getDeclaredConstructors()==com.itheima.Emp(java.lang.String)
c.getDeclaredConstructors()==public com.itheima.Emp(java.lang.String,int)
*/
}
}
}


对于方法,字段,构造方法之类用类获取记住四个:获取全部,获取特定,暴力获取全部,暴力获取特定!

package com.itheima;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

class AB{
protected String name;
protected String id;
}
@Deprecated
public class MethodClass extends AB{
void show(){}
public void say(){}
private int age;
public char c;
private boolean b;
public static void main(String[] args) throws Exception {
Class<MethodClass> c = MethodClass.class;
//获取所有的(包含父类的方法)public修饰的方法
Method[] m = c.getMethods();
for (Method method : m) {
System.out.println(method);
}
//总结:4个方法,获取全部,获取特定;不受修饰符影响的全部,不受修饰符影响的特定;(前两个都还是受限制的)

//获取指定的方法
Method me = c.getMethod("main", String[].class);
System.out.println("main "+me);//main public static void junereflect624.MethodDemo5.main(java.lang.String[]) throws java.lang.Exception

//访问所有方法,不受访问权限影响
m = c.getDeclaredMethods();
for (Method method : m) {
System.out.println("不受影响的:"+method);
}

me = c.getDeclaredMethod("show");
System.out.println(me);//void junereflect624.MethodDemo.show()

me = c.getMethod("toString");
System.out.println(me);//public java.lang.String java.lang.Object.toString()

/**
* Method[] getDeclaredMethods()
返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,
包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法,只可以对当前类有效
*/
/*me = c.getDeclaredMethod("toString");//ERROR,c.getDeclaredMethod()不能得到继承的方法
System.out.println(me);//public java.lang.String java.lang.Object.toString()
*/
//得到字段
Field[] f = c.getFields();
for (Field field : f) {//只得到了public的
System.out.println("字段"+field);
}

//特定字段
Field fi = c.getField("c");//""里面是名称
System.out.println(fi);//public char junereflect624.MethodDemo.c

//得到不受限定名限定的全部字段
f = c.getDeclaredFields();
for (Field field : f) {//得到不受修饰符限定的字段,但是只对当前类有效
System.out.println("全部字段:"+field);
/**
*  全部字段:private int junereflect624.MethodDemo.age
全部字段:public char junereflect624.MethodDemo.c
全部字段:private boolean junereflect624.MethodDemo.b
*/
}
//注释  Annotation
Annotation[] a = c.getAnnotations();
System.out.println(a.length);
for (Annotation annotation : a) {
System.out.println(annotation);
}

//特定注解
Deprecated d = c.getAnnotation(Deprecated.class);
System.out.println(d);
}
}


一下是字段获取

package july78javaEnhance;

import java.lang.reflect.Field;

class Stu{
public String name;
public String sex;
public int age;

public Stu(String name, String sex, int age) {
super();
this.name = name;
this.sex = sex;
this.age = age;
}
}

public class ReflectDemo6 {
public static void main(String[] args) throws Exception {
Stu s = new Stu("刘昭", "男", 12);

Class<Stu> c = Stu.class;

Field f = c.getField("name");
System.out.println(f.get(s));////从哪个对象身上取!此时显示刘昭!
//	修改对象的值
/**
Field f = c.getField("name");
f.set(s,"章泽天");
System.out.println(f.get(s));//从哪个对象身上取!//此时显示章泽天
*/
}
}


---------------------- 拖走FM----期待与您交流! --------

收音机,电台,网上电台,广播,在线广播,网络广播,广播电台,网络电台,在线电台,电台在线收听,广播电台在线收听,网络电台在线收听,在线收听电台,fm收音机,网络收音机,广播下载,在线收音机,收音机软件下载,电台软件下载,网络收音机下载--------------

---------------------- 拖走FM----期待与您交流! --------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: