Java学习笔记八(反射)
来源:互联网 发布:好看的淘宝头像图片 编辑:程序博客网 时间:2024/06/08 12:36
1.介绍
反射为Java程序在运行时提供了动态的能力,利用反射可以在运行时对程序进行动态的控制。本篇博客着重讲解一下Java中的反射。
2.Class类的使用
在Java运行过程中,每个类被加载后都会在内存中产生一个对应的Class类对象,因此通过Class类的对象就可以拿到有关类的相关信息。下面演示一个实例。
<span style="font-family:SimSun;font-size:18px;">package com.Reflect;//用来被加载类的父类class MyFather {//父类的公共成员变量public int memberFather;//父类的公共方法public void methodFather(){System.out.println("我是从父类继承而来的方法methodFather!!!");}}//用来被加载的类class MySon extends MyFather {//子类的公共成员变量public int memberSonPublic;//子类的私有成员变量private int memberSonPrivate;//子类的公共方法public void methodSonPublic(){System.out.println("我是子类自己的方法methodSonPublic!!!");}//子类的保护方法protected void methodSonProtected(){System.out.println("我是子类自己的方法methodSonProtected!!!");}}//主类public class Sample34_1{public static void main(String args[]){ try { //加载指定的类 Class c=Class.forName("com.Reflect.MySon"); //创建加载类的对象 MySon ms=(MySon)c.newInstance(); System.out.println(ms.getClass()); //调用创建对象的方法 System.out.println("===============调用创建对象的方法==================="); ms.methodSonProtected(); ms.methodSonPublic(); ms.methodFather(); //打印加载类的详细信息 System.out.println("==================加载类的信息======================"); System.out.println(c.getName()+"类自己声明了" +c.getDeclaredFields().length+"个成员变量。"); System.out.println(c.getName()+"类对外公布的方法有" +c.getMethods().length+"个。"); } catch(Exception e) { e.printStackTrace(); }}}</span>上面的实例通过Class对象的ForName方法加载相应的class对象,并通过Class对象的newInstance方法创建了其对象,紧接着调用了对象中的方法,接着打印了加载类的一些信息。
3.Field类的使用
Field类的对象代表成员变量,携带成员变量的信息,注意的是与Class类类似,不可以通过构造器创建Field类的对象,对象都是通过Class类对象提供的get系列方法创建出来的。
<span style="font-family:SimSun;font-size:18px;">package com.Reflect;import java.util.*;import java.lang.reflect.*;//自定义用来测试的类class Student{public int sage;//年龄private int sno;//学号public boolean gender;//性别 true-男 false-女public String sname;//姓名//构造器public Student(int sage,int sno,boolean gender,String sname){this.sage=sage;this.sno=sno;this.gender=gender;this.sname=sname;}}//主类public class Sample34_4{public static void main(String args[]){ try { //创建Student类对象 Student tom=new Student(21,10001,true,"Tom"); //获取Student类对应的Class对象 Class dc=tom.getClass(); //获取Student类所有可以访问的成员变量对应的Field数组 Field[] fieldArray=dc.getFields(); //打印Student类对象各成员变量的详细信息 System.out.println("成员变量名\t成员变量类型\t\t成员变量值"); int size=fieldArray.length; //循环处理Field数组 for(int i=0;i<size;i++) { Field tempf=fieldArray[i]; //打印成员变量名称 System.out.print(tempf.getName()+"\t\t"); //打印成员变量类型 System.out.print(tempf.getType().toString() +((tempf.getType().toString().length()>7)?"\t":"\t\t\t")); //打印成员变量值 System.out.println(tempf.get(tom)); } }catch(Exception e){e.printStackTrace();}}}</span>
上述实例中,首先定义了Strudent类的对象,然后通过Student类对应的Class对象获取可以访问的成员变量的Field数组,紧接着就是调用Field类的方法,对成员变量的信息进行打印操作
4.Method类的使用
Method类的对象代表一个方法,携带方法有关的信息,该对象只能通过Class类对象的get方法进行得到
<span style="font-family:SimSun;font-size:18px;">package com.Reflect;import java.util.*;import java.lang.reflect.*;//自定义用来测试的类class ForMethod {//声明静态方法sayHello,功能为在屏幕上打印字符串public static void sayHello(String name){System.out.println("你好,"+name+"!!!");}//声明非静态方法generateNum,功能为产生min与max之间的随机数public String generateNum(int max,int min){return (Math.random()*(max-min)+min)+"";}}//主类public class Sample34_5{public static void main(String args[]){ try { //创建ForMethod类对象 ForMethod fm=new ForMethod(); //获取ForMethod类对应的Class对象 Class fmc=fm.getClass(); //获取可以访问的方法对应的Method数组 Method[] ma=fmc.getMethods(); //对数组进行扫描打印方法的信息 System.out.println("方法名称\t返回值类型\t\t参数列表"); int size=ma.length; for(int i=0;i<size;i++) { Method tempm=ma[i]; //打印方法名称 String mname=tempm.getName(); System.out.print(mname+((mname.length()>7)?"\t":"\t\t")); //打印方法的返回值类型 String mReturnType=tempm.getReturnType().getName(); System.out.print(mReturnType+((mReturnType.length()>15)?"\t": (mReturnType.length()>10)?"\t\t":"\t\t\t")); //循环打印方法的参数序列 Class[] ca=tempm.getParameterTypes(); int csize=ca.length; if(csize==0) { System.out.print("没有参数"); } for(int j=0;j<csize;j++) { System.out.print(ca[j].getName()+((j==csize-1)?"":", ")); } //换行 System.out.println(); } //通过反射调用静态方法sayHello System.out.println("==========通过反射调用静态方法sayHello==========="); ma[0].invoke(null,new Object[]{"王强"}); //通过反射调用非静态方法generateNum System.out.println("========通过反射调用非静态方法generateNum========"); System.out.println(ma[1].invoke(fm, new Object[]{new Integer(100),new Integer(1000)})); }catch(Exception e){e.printStackTrace();} }}</span>
该实例中首先创建了ForMethod类的对象,然后通过反射打印了Formethod类的所有可以访问到的方法,最后通过反射调用了ForMethod类中声明的两个方法
5.Constructor类的使用
Constructor类代表一个构造器,携带有关构造器的相关信息,也是只能通过Class类对象的get系列方法获得。
<span style="font-family:SimSun;font-size:18px;">package com.Reflect;import java.util.*;import java.lang.reflect.*;//自定义用来测试的类class Student1{String sname;//姓名int sage;//年龄//声明无参构造器public Student1(){sname="Tom";sage=23;}//声明有参构造器public Student1(String sname,int sage){this.sname=sname;this.sage=sage;}//声明一个普通方法public void sayHello(){System.out.println("您好,我是"+sname+",今年"+sage+"岁!!!");}}//主类public class Sample34_6{public static void main(String args[]){ try { //获取Student类对应的Class对象 Class sc=Student1.class; //获取可以访问的构造器对应的Constructor数组 Constructor[] ca=sc.getConstructors(); //对数组进行扫描打印构造器的信息 System.out.println("构造器名称\t\t参数列表"); int size=ca.length; for(int i=0;i<size;i++) { Constructor tempc=ca[i]; //打印构造器名称 String cname=tempc.getName(); System.out.print(cname+"\t\t"); //循环打印构造器的参数序列 Class[] pa=tempc.getParameterTypes(); int psize=pa.length; if(psize==0) { System.out.print("没有参数"); } for(int j=0;j<psize;j++) { System.out.print(pa[j].getName()+((j==psize-1)?"":", ")); } //换行 System.out.println(); } //使用反射调用有参构造器创建对象 Student1 stu=(Student1)ca[0].newInstance(new Object[0]); //调用创建对象的sayHello方法 stu.sayHello(); //使用反射调用有参构造器创建对象 stu=(Student1)ca[1].newInstance(new Object[]{"王强",new Integer(25)}); //调用创建对象的sayHello方法 stu.sayHello(); }catch(Exception e){e.printStackTrace();}}}</span>
上述实例中,首先获得了Student类对应的Class对象,紧接着打印了所有Student类可以访问的构造器的信息,最后通过反射调用了Student类的构造器创建了两个对象并调用了SayHello方法。
6.取消访问限制
当用Class对象的getDeclaredXXXs方法获得Field、Method或Constructor时,由于访问修饰符的限制,可能有些字段、方法或者构造器访问不到。如果要访问的话,需要先解除限制,然后再访问
若希望解除限制,需要使用java.lang.reflect.AccessibleObject类。
<span style="font-family:SimSun;font-size:18px;">package com.Reflect;import java.lang.reflect.*;//自定义用来测试的类class Employee1{private String sname;//员工姓名//私有方法private void sayHello(){System.out.println("您好,我是"+sname +",恭喜您成功访问了private的方法sayHello!!!");}}//主类public class Sample34_8{public static void main(String args[]){try{//创建Employee对象Employee1 tom=new Employee1();//获取Employee类对应的Class对象Class ec=tom.getClass();//获取Employee类声明的成员变量对应的Field数组Field[] fa=ec.getDeclaredFields();//设置sname成员变量的访问限制为允许fa[0].setAccessible(true);//设置sname成员变量的值fa[0].set(tom,"Tom");//获取Employee类声明的方法对应的Method数组Method[] ma=ec.getDeclaredMethods();//设置所有方法的访问限制为允许//ma[0].setAccessible(true);AccessibleObject.setAccessible(ma,true);//调用sayHello方法ma[0].invoke(tom,new Object[0]);}catch(Exception e){e.printStackTrace();} }}</span>
上述实例就是通过解除访问修饰符的限制来访问到私有变量。
0 0
- Java学习笔记八(反射)
- java笔记(八):反射
- 黑马程序员学习笔记之八(Java 反射机制)
- java学习笔记(八)
- Java学习笔记(八)
- Java学习笔记(八)
- Java学习笔记(八)
- java学习笔记(八)
- Java-反射(学习笔记)
- java学习笔记(八)
- Java学习笔记八
- iOS学习笔记48-Swift(八)反射
- Java 反射学习笔记
- Java反射学习笔记
- java反射学习笔记
- Java反射学习笔记
- Java 反射学习笔记
- Java反射学习笔记
- CSDN博客积分规则
- EazyUI布局问题
- ubuntu启动过程
- 求二叉树的深度和宽度[Java]
- Windows环境下Android Studio v1.0安装教程
- Java学习笔记八(反射)
- “The connection to adb is down, and a severe error has occured”的解决方法汇总
- QString & String
- 无刷新上传
- ssh 免密码登录配置
- Cocos-js——粒子系统
- 基于FT5x06嵌入式Linux电容触摸屏驱动
- 论文提要“Selective Search for Object Recognition”
- SimpleDateFormat 源码解析