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>

上述实例就是通过解除訪问修饰符的限制来訪问到私有变量。

Java学习笔记八(反射)的更多相关文章

  1. java学习笔记:反射

    1.什么是反射? Reflection(反射)是被视为动态语言的关键,反射机制允许程序做执行期间借助于ReflectionAPI取得任何类的内部信息,并能直接操作任意对象内部属性及方法 2.反射相关的 ...

  2. 【java学习笔记】反射基础

    一.反射 反射就是在剖析一个类,了解这个类的构造,创建这个类对应的对象. Class 代表字节码的类,代表类的类 Field 代表属性的类 Method 代表方法的类 Constructor 代表构造 ...

  3. 8.2(java学习笔记)反射

    一.基础知识 对象是表示或封装一些数据,一个类被加载后JVM会创建一个对应该类的Class对象, 类的整个结构信息会被放在对应的对象中,通过这个对象我们可以获取改类的全部信息, 而这些操作称为反射. ...

  4. Java 学习笔记(15)——反射

    Java中的类文件最终会被编译为.class 文件,也就是Java字节码.这个字节码中会存储Java 类的相关信息.在JVM执行这些代码时首先根据 java 命令中指定的类名找到.class 文件然后 ...

  5. java学习笔记之反射—Class类实例化和对象的反射实例化

    反射之中所有的核心操作都是通过Class类对象展开的,可以说Class类是反射操作的根源所在,但是这个类的实例化对象,可以采用三种方式完成. java.lang.Class类的定义: public f ...

  6. Java 学习笔记 (八) Java 变量

    head first java page85 实例变量是声明在类内而不是方法中 class Horse{ private double height=15.2; private String bree ...

  7. Java学习笔记八:Java的流程控制语句之循环语句

    Java的流程控制语句之循环语句 一:Java循环语句之while: 生活中,有些时候为了完成任务,需要重复的进行某些动作.如参加 10000 米长跑,需要绕 400 米的赛道反复的跑 25 圈.在 ...

  8. Java学习笔记八

    IO流:就是input/output输入/输出流. 一.字节流操作文件的便捷类:FileWriter和FileReader import java.io.FileWriter; import java ...

  9. java学习笔记之反射—反射和工厂模式

    简单工厂模式又称为静态工厂方法模式,它是由工厂对象来决定要创建哪一种类的实例化对象. 静态工厂代码: class Factory{ private Factory() {} public static ...

随机推荐

  1. 前端学PHP之正则表达式函数

    前面的话 正则表达式不能独立使用,它只是一种用来定义字符串的规则模式,必须在相应的正则表达式函数中应用,才能实现对字符串的匹配.查找.替换及分割等操作.前面介绍了正则表达式的基础语法,本文将详细介绍正 ...

  2. python垃圾回收三之标记清除

    #第一组循环引用# a = [1,2] b = [3,4] a.append(b) b.append(a) del a ## #第二组循环引用# c = [4,5] d = [5,6] c.appen ...

  3. GDB命令

    recursiveDescription 打印view层次结构

  4. gitminer

    https://github.com/UnkL4b/GitMiner + Autor: UnK + Blog: https://unkl4b.github.io + Github: https://g ...

  5. 【Python】HackBack(获取暴力破解服务器密码的IP来源)

    1.前言 又在0x00sec上翻到好东东. https://0x00sec.org/t/python-hackback-updated/882 帖子里的脚本会得到那些暴力服务器密码失败的IP和用户名, ...

  6. eclipse安装阿里巴巴java开发规范插件

    阿里巴巴java开发规范插件 作为JAVA开发人员,始终没有一个明确的规范,何为好代码,何为坏代码,造成不同人的代码风格不同,接手别人代码后改造起来相当困难.前不久,阿里巴巴发布了<阿里巴巴Ja ...

  7. idea项目左边栏只能看到文件看不到项目结构

    1.点击file->project structure..->Modules 点击右上角+加号 ->import Modules 2.选择你的项目,点击确定 3.在如下页面选择imp ...

  8. HTTPS-加密SSL证书

    从第一部分HTTP工作原理中,我们可以了解到HTTPS核心的一个部分是数据传输之前的握手,握手过程中确定了数据加密的密码.在握手过程中,网站会向浏览器发送SSL证书,SSL证书和我们日常用的身份证类似 ...

  9. poj 2524 求连通分量(并查集模板题)

    求连通分量 Sample Input 10 91 21 31 41 51 61 71 81 91 1010 42 34 54 85 80 0Sample Output Case 1: 1Case 2: ...

  10. K8S Dashborad登陆认证文档

    K8S Dashboard是官方的一个基于WEB的用户界面,专门用来管理K8S集群,并可展示集群的状态.因为我们使用kubeadm搭建的集群会默认开启RABC(角色访问控制机制),所以我们必须要进行额 ...