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

java反射学习-以demo加理伦

2016-09-21 11:39 351 查看

一、首先介绍一下Class类是什么?

1.class类的实例表示java应用运行时的类(class ans enum)或接口(interface and annotation)(每个java类运行时都在JVM里表现为一个class对象,可通过类名.class,类型.getClass(),Class.forName(“类名”)等方法获取class对象)。数组同样也被映射为为class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本类型boolean,byte,char,short,int,long,float,double和关键字void同样表现为 class 对象。(哈哈,以上均来自百度)

2.class的主要方法

class类的方法还是挺多的。主要是用于得到运行时类的相关信息(可用于反射)。

重要的几个方法:

1, public static Class<?> forName(String className) :natice 方法,动态加载类。非常重要。
如在sql中动态加载驱动程序:class.forName(sqlDriver);

2,public T newInstance() :根据对象的class新建一个对象,用于反射。非常重要。
可用在反射中构建对象,调用对象方法:

class doubleClass= class.forName("java.lang.Double");

Object objDouble = doubleClass.newInstance();

如在javaBean中就应用了这个方法,因为java默认要有一个无参构造函数。

3, public ClassLoader getClassLoader() :获得类的类加载器Bootstrap  ,Extension ,System or user custom      ClassLoader(一般为system classloader)。重要。

4,public String getName() :获取类或接口的名字。记住enum为类,annotation为接口。重要

5,public native Class getSuperclass():获取类的父类,继承了父类则返回父类,否则返回java.lang.Object。返回Object的父类为空-null。一般
6,public java.net.URL getResource(String name) :根据字符串获得资源。

7,其他类

public boolean isEnum() :判断是否为枚举类型。

public native boolean isArray() :判断是否为数组类型。

public native boolean isPrimitive() :判断是否为基本类型。
public boolean isAnnotation() :判断是否为注解类型。

public Package getPackage() :反射中获得package,如java.lang.Object 的package为java.lang。

public native int getModifiers() : 反射中获得修饰符,如public static void等 。

public Field getField(String name):反射中获得域成员。

public Field[] getFields() :获得域数组成员。
public Method[] getMethods() :获得方法。

public Method getDeclaredMethod(String name, Class<?>... parameterTypes):加个Declared代表本类,继承,父类均不包括。

public Constructor<?>[] getConstructors() :获得所有的构造函数。


案例一,获取Class对象:

/**
* 每个java类运行时都在JVM里表现为一个class对象,
* 1.可通过类名.class,
* 2.对象.getClass(),
* 3.Class.forName("类名")
* 等方法获取class对象
* @author hxy
*
*/
public class Test {
public static void main(String[] args) {
Class<?> c1=null;
Class<?> c2=null;
Class<?> c3=null;
try {
//通过类路径获取Class
c1=Class.forName("com.cdc.console.controller.Test");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//通过对象获取Class
c2=new Test().getClass();
//通过类名获取Class
c3=Test.class;
System.out.println("类名称   "+c1.getName());
System.out.println("类名称   "+c2.getName());
System.out.println("类名称   "+c3.getName());
}
}


案例二:通过Class实例化对象 newInstance(),类必须有无参构造函数

/**
* 通过Class实例化对象 newInstance(),类必须有无参构造函数,否则会报错
* 1.可通过类名.class,
* 2.对象.getClass(),
* 3.Class.forName("类名")
* 等方法获取class对象
* @author hxy
*
*/
public class Test {
public static void main(String[] args) {
Class<?> conf=SysConfLog.class;
//        Class<?> conf=new SysConfLog().getClass();
//        Class<?> conf=Class.forName("com.cdc.entity.sys.SysConfLog");
try {
SysConfLog c = (SysConfLog) conf.newInstance();
c.setBuName("哈哈");
System.out.println(c.getBuName());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}

}


案例三:通过Class取得全部的构造函数

/**
* 通过Class取得所有构造函数getConstructors(),实例化对象 newInstance()
* 1.可通过类名.class,
* 2.对象.getClass(),
* 3.Class.forName("类名")
* 等方法获取class对象
* @author hxy
*
*/
public class Test {
public static void main(String[] args) {
Class<?> conf=SysConfLog.class;
//        Class<?> conf=new SysConfLog().getClass();
//        Class<?> conf=Class.forName("com.cdc.entity.sys.SysConfLog");
Constructor<?>[] ars = conf.getConstructors();
try {
SysConfLog c = (SysConfLog) ars[0].newInstance();
SysConfLog c1 = (SysConfLog) ars[1].newInstance("我是叫hxy");
c.setMenuName("我不是hxy");
System.out.println(c.getMenuName());
System.out.println(c1.getMenuName());
} catch (Exception e) {
e.printStackTrace();
}

}
}


注:以节省页面,以下只写出代码核心部分

案例四:返回一个类实现的接口

//保存所有的接口
Class<?> intes[]=demo.getInterfaces();
for (int i = 0; i < intes.length; i++) {
System.out.println("实现的接口   "+intes[i].getName());
}


案例五:返回一个类继承的类

//取得父类
Class<?> temp=demo.getSuperclass();
System.out.println("继承的父类为:   "+temp.getName());


案例六:取出构造函数的详细信息

/**
* 通过Class取得所有构造函数getConstructors(),取出构造函数的详细信息
* 1.可通过类名.class,
* 2.对象.getClass(),
* 3.Class.forName("类名")
* 等方法获取class对象
* @author hxy
*
*/
public class Test {
public static void main(String[] args) {
Class<?> conf=SysConfLog.class;
//        Class<?> conf=new SysConfLog().getClass();
//        Class<?> conf=Class.forName("com.cdc.entity.sys.SysConfLog");
Constructor<?>cons[]=conf.getConstructors();
for (int i = 0; i < cons.length; i++) {
//获取参数类型集合
Class<?> p[]=cons[i].getParameterTypes();
System.out.print("构造方法:  ");
//获取修饰符的字节码,就是返回一个以特定字节码(十六进制)表示的整数
int mo=cons[i].getModifiers();
System.out.print(Modifier.toString(mo)+" ");
//获取类路径
System.out.print(cons[i].getName());
System.out.print("(");
//循环参数列表
for(int j=0;j<p.length;++j){
System.out.print(p[j].getName()+" arg"+i);
if(j<p.length-1){
System.out.print(",");
}
}
System.out.println("){}");
}
}


案例七:获取所有的方法,获取方法的异常

/**
* 通过Class取得所有方法,取出方法的详细信息,有异常,打印异常
* 1.可通过类名.class,
* 2.对象.getClass(),
* 3.Class.forName("类名")
* 等方法获取class对象
* @author hxy
*
*/
public class Test {
public static void main(String[] args) {
Class<?> conf=SysConfLog.class;
//        Class<?> conf=new SysConfLog().getClass();
//        Class<?> conf=Class.forName("com.cdc.entity.sys.SysConfLog");
//获取所有方法
Method method[]=conf.getMethods();
for(int i=0;i<method.length;++i){
//返回类型
Class<?> returnType=method[i].getReturnType();
//参数类型
Class<?> para[]=method[i].getParameterTypes();
///获取修饰符的字节码,就是返回一个以特定字节码(十六进制)表示的整数
int temp=method[i].getModifiers();
//通过字节码,获取修饰符
System.out.print(Modifier.toString(temp)+" ");
System.out.print(returnType.getName()+"  ");
System.out.print(method[i].getName()+" ");
System.out.print("(");
for(int j=0;j<para.length;++j){
System.out.print(para[j].getName()+" "+"arg"+j);
if(j<para.length-1){
System.out.print(",");
}
}
//方法的抛出异常
Class<?> exce[]=method[i].getExceptionTypes();
if(exce.length>0){
System.out.print(") throws ");
for(int k=0;k<exce.length;++k){
System.out.print(exce[k].getName()+" ");
if(k<exce.length-1){
System.out.print(",");
}
}
}else{
System.out.print(")");
}
System.out.println();
}
}


案例八:通过Class取得所有属性,分为本类和父类

/**
* 通过Class取得所有属性,分为本类和父类
* 1.可通过类名.class,
* 2.对象.getClass(),
* 3.Class.forName("类名")
* 等方法获取class对象
* @author hxy
*
*/
public class Test {
public static void main(String[] args) {
Class<?> conf=SysConfLog.class;
//        Class<?> conf=new SysConfLog().getClass();
//        Class<?> conf=Class.forName("com.cdc.entity.sys.SysConfLog");
//获取所有方法
System.out.println("===============本类属性========================");
// 取得本类的全部属性
Field[] field = conf.getDeclaredFields();
for (int i = 0; i < field.length; i++) {
// 权限修饰符
int mo = field[i].getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = field[i].getType();
System.out.println(priv + " " + type.getName() + " "
+ field[i].getName() + ";");
}
System.out.println("===============实现的接口或者父类的属性========================");
// 取得实现的接口或者父类的属性
Field[] filed1 = conf.getFields();
for (int j = 0; j < filed1.length; j++) {
// 权限修饰符
int mo = filed1[j].getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = filed1[j].getType();
System.out.println(priv + " " + type.getName() + " "
+ filed1[j].getName() + ";");
}
}


案例九:调用类的set get 方法:

public static void main(String[] args) {
Class<?> conf=SysConfLog.class;
//        Class<?> conf=new SysConfLog().getClass();
//        Class<?> conf=Class.forName("com.cdc.entity.sys.SysConfLog");
// 取得本类的全部属性
Object obj=null;
try {
obj=conf.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
Field[] field = conf.getDeclaredFields();
//赋值
setter(obj, "clientMark", "clientMark", String.class);
setter(obj, "clientIp", "clientIp", String.class);
for (int i = 0; i < field.length; i++) {
getter(obj, field[i].getName());
}
}
/**
* @param obj
*            操作的对象
* @param att
*            操作的属性
* */
public static void getter(Object obj, String att) {
try {
att=att.substring(0,1).toUpperCase()+att.substring(1,att.length());
Method method = obj.getClass().getMethod("get" + att);
if(method.invoke(obj)==null){
return;
}
System.out.println(method.invoke(obj));
} catch (Exception e) {
e.printStackTrace();
}
}

/**
* @param obj
*            操作的对象
* @param att
*            操作的属性
* @param value
*            设置的值
* @param type
*            参数的属性
* */
public static void setter(Object obj, String att, Object value,
Class<?> type) {
att=att.substring(0,1).toUpperCase()+att.substring(1,att. length());
try {
Method method = obj.getClass().getMethod("set" + att, type);
method.invoke(obj, value);
} catch (Exception e) {
e.printStackTrace();
}
}


案例十:通过反射修改数组信息和改变数组长度

/**
* 通过反射修改数组信息和改变数组长度
* @author hxy
*
*/
public class Test {
public static void main(String[] args) {
int[] temp={1,2,3,4,5};
Class<?>demo=temp.getClass().getComponentType();
System.out.println("数组类型: "+demo.getName());
System.out.println("数组长度  "+Array.getLength(temp));
System.out.println("数组的第一个元素: "+Array.get(temp, 0));
Array.set(temp, 0, 100);
System.out.println("修改之后数组第一个元素为: "+Array.get(temp, 0));
temp=(int[]) arrayInc(temp, 7);
print(temp);
}
/**
* 修改数组大小
* */
public static Object arrayInc(Object obj,int len){
//返回obj数组类型,如果不是数组则返回Null
Class<?>arr=obj.getClass().getComponentType();
Object newArr=Array.newInstance(arr, len);
int co=Array.getLength(obj);
//复制数组 obj-源数组 ,0-从0开始复制  ,newArr-目标数组 ,0-复制到新数组从0开始,co-复制多少长度
System.arraycopy(obj, 0, newArr, 0, co);
return newArr;
}
/**
* 打印
* */
public static void print(Object obj){
Class<?>c=obj.getClass();
if(!c.isArray()){
return;
}
System.out.println("数组长度为: "+Array.getLength(obj));
for (int i = 0; i < Array.getLength(obj); i++) {
System.out.print(Array.get(obj, i)+" ");
}
}


由于平时很少写博客,写的很差,请多见谅。

这里推荐下我的开源项目:

hxyFrame是一个OA办公系统,采用流行的框架springMvc+spring+mybatis+shiro+ehcache开发,还集成了权限管理(菜单权限、数据权限),完善的代码生成器,solr全文搜索引擎,activiti工作流程引擎,cas单点登陆等功能,后期还会考虑改造成Dubbo微服务化,做到模块的相对独立,使用更加灵活,努力做到快速开发OA办公系统。 感兴趣可以Watch、Start持续关注项目最新状态,加入QQ群:210315502

oschina仓库:https://git.oschina.net/huangxianyuan/hxyFrame.git

github仓库:https://github.com/huangxianyuan/hxyFrame.git
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: