JAVA 学习笔记 - 反射机制
1. JAVA反射机制的概念
2. 怎样实例化一个 Class对象
Class.forName(包名.类名);
对象.getClass();
类.class;
============================代码===================================
package org.liys.getclass;
class Y{
};
public class GetClass02{
public static void main(String args[]){
Class<?> c1 = null;
Class<?> c2 = null;
Class<?> c3 = null;
//日常开发中常用的一种实例化形式
try{
c1 = Class.forName("org.liys.getclass.Y");
}catch(ClassNotFoundException e){}
c2 = new Y().getClass(); //通过object类中的方法实例化
c3 = Y.class; //通过类.class实例化
System.out.println(c1.getName());
System.out.println(c2.getName());
System.out.println(c3.getName());
}
}
3.Class类的使用
用Class类的newInstance来替代掉一般的new操作。
不过需要保证的是,类的申明中,需要有无参构造函数。
.....
Class<?> c = null;
c = Class.forName(包名.类名);
类的实例化对象 = (类) c.newInstatnce(); (object 向下转型)
对象.setName(), 对象.setage();
......
很少会用带有有参构造函数的类来做实例化,但如果有的话,可以用Constructor来解决。
使用getConstructors来获取该类所有的构造函数 cons[],并用下标来调用cons[0],cons[1]。
===========================代码=============================
package org.liys.newinstance;
import java.lang.reflect.Constructor;
class Person{
private String name;
private int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
public void setName(String name){
this.name = name;
}
public void setAge(int age){
this.age = age;
}
public String getName(){
return this.name;
}
public int getAge(){
return this.age;
}
public String toString(){
return "姓名: " + this.name + " 年龄: "+ this.age;
}
}
public class GetPerson{
public static void main(String args[]){
Class<?> c = null;
try{
c = Class.forName("org.liys.newinstance.Person");
} catch(ClassNotFoundException e){
e.printStackTrace();
}
Person p = null;
Constructor<?> cons[] = null;
cons = c.getConstructors();
try{
p = (Person) cons[0].newInstance("李柯",30);
}catch(Exception e){
e.printStackTrace();
}
//p.setName("李柯");
//p.setAge(30);
System.out.println(p);
}
}
4.取得类(.class)的结构
最重要是获取类的对象, Class<?> c1 = Class.forName(报名.类名);
a. 获取类的父类 从java doc中查询 Class中获取父类的方法
Class<?> c2 = c1.getSuperclass(); .....c2.getName();
b.获取该类中所有的方法,包括方法的参数,抛出异常,返回值等
通过Class中的getMethods()方法获得所有的方法包括从父类继承的方法
或者通过Class中的getDeclaredMethods()
方法,只是获得该类中定义的方法。
然后再根据Method类去查如何获得函数的参数,返回值,权限范围,抛出异常等
代码=========================================================================
package org.lxh.demo15;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class GetMethodDemo {
public static void main(String args[]){
Class<?> c1 = null;
try{
c1 = Class.forName("org.lxh.demo15.Person"); //获取类对象
}catch(ClassNotFoundException e){
e.printStackTrace();
}
Method[] m = c1.getMethods(); //获取类中所有的方法
String mod = null;
String parm = "";
String Except = "";
for(int i=0; i<m.length;i++){
parm = "";
Except = "";
mod = Modifier.toString(m[i].getModifiers()); //获取方法的权限访问范围
Class<?> rettype = m[i].getReturnType(); //获取方法的返回值
Class<?>[] p = m[i].getParameterTypes(); //获取方法中的参数
for(int j= 0;j<p.length;j++){
parm = parm + p[j].getName() +" arg["+j+"]";
if (j < (p.length -1)){
parm = parm + ",";
}
}
Class<?>[] Ex = m[i].getExceptionTypes(); //获取方法抛出的异常,一是Class类型
if (Ex.length > 0){
Except = " throws ";
for(int j= 0;j<Ex.length;j++){
Except = Except + Ex[j].getName() ;
if (j < (Ex.length -1)){
Except = Except + ",";
}
}
}
System.out.println(mod + " " +rettype+" "+ m[i].getName() +"("+parm+")" +" "+Except);
}
}
}
c.获取实现的接口类
........
Class<?> c[] = c1.getInterfaces() ; // 以数组形式返回实现的全部接口
for(int i=0;i<c.length;i++){
System.out.println("实现的接口名称:" + c[i].getName()) ; // 输出接口名称
}
........
d.获取类的属性
Field f[] = c1.getDeclaredFields() ; // 取得本类中的属性
Field f[] = c1.getFields() ; // 取得本类中的公共属性包括继承自父类或实现的接口类中的
.......
Field f[] = c1.getFields() ; // 取得本类中的公共属性
for(int i=0;i<f.length;i++){
Class<?> r = f[i].getType() ; // 得到属性类型
int mo = f[i].getModifiers() ; // 得到修饰符的数字
String priv = Modifier.toString(mo) ; // 还原修饰符
System.out.print(priv + " ") ;
System.out.print(r.getName() + " ") ; // 得到属性类型
System.out.print(f[i].getName()) ; // 输出属性名称
System.out.println(" ;") ;
}
..........
e.获取类的所有构造方法
Constructor<?> con[] = c1.getConstructors() ;
之后与Method相同,查找Constructor 的参数,访问权限范围。
5. Java反射机制的深入研究
a.怎样执行给定.class类文件中的无参函数
Class c1 = Class.forName(包名.类名);
Method mt = c1.getMethod(方法名);
mt.invoke(c1.newInstance());
代码==================================================
...
Class<?> c1 = null;
try{
c1 = Class.forName("org.lxh.demo15.Person");
Method mt = null;
mt = c1.getMethod("sayChina");
mt.invoke(c1.newInstance());
}catch(Exception e){
e.printStackTrace();
}
...
b.怎样执行给定.class类文件中的带参函数
Class c1 = Class.forName(包名.类名);
Method mt = c1.getMethod(方法名, 参数类型.class);
mt.invoke(c1.newInstance(),参数);
代码=========================================
......
Class<?> c1 = null;
try{
c1 = Class.forName("org.lxh.demo15.Person");
Method mt = null;
mt = c1.getMethod("sayHello",String.class,int.class);
String tmp = (String) mt.invoke(c1.newInstance(),"李柯",31);
System.out.println(tmp);
}catch(Exception e){
e.printStackTrace();
}
..........
b.怎样执行给定.class类文件中的get set函数
先写一个将第一个字母变大写的函数,以方便getMethod方法获取getName等方法名
写setter, getter函数,主要为了实现各个类型参数的统一接口赋值。
代码=====================================================
public static void main(String args[]){
Class<?> c1 = null;
Object obj = null;
try{
c1 = Class.forName("org.lxh.demo15.Person");
obj = c1.newInstance();
setter(obj,"name","李宇扬",String.class);
setter(obj,"age",5,int.class);
String name = (String)getter(obj,"name");
int age = (int)getter(obj,"age");
System.out.println("我的名字叫"+ name +"今年 "+age+" 岁啦 ");
}catch(Exception e){
e.printStackTrace();
}
}
public static void setter(Object obj,String attr,Object val,Class<?> c){
String temp = "set" + getUpperStr(attr);
try{
System.out.println(temp);
Method mt = obj.getClass().getMethod(temp,c);
mt.invoke(obj,val);
}catch(Exception e){}
}
public static Object getter(Object obj,String attr) throws Exception{
String temp = "get" + getUpperStr(attr);
System.out.println(temp);
Method mt = null;
try{
mt = obj.getClass().getMethod(temp);
return mt.invoke(obj);
}catch(Exception e){
return null;
}
}
public static String getUpperStr(String str){
String temp = str.substring(0,1). toUpperCase()+ str.substring(1);
return temp;
}
c.怎样获取数组对象的类型,长度,内容
通过java.lang.reflect.Array类获取
Array.getLength(obj), obj.getClass().getComponentType().getName; Array.get(obj,index);
代码==================================
int arr[] = {1,2,3,4,5};
int arrlen = 0;
arrlen=Array.getLength(arr);
String tp = arr.getClass().getComponentType().getName();
System.out.println(tp + "类型的数组长度为 "+ arrlen);
System.out.println(tp + "类型数组的第一个元素 "+ Array.get(arr,0));
Array.set(arr,0,9);
System.out.println(tp + "类型数组的第一个元素 "+ Array.get(arr,0));
d.怎样改变数组的大小
还是通过Array类,的newInstance(Class<?>,int length),新建一个数组对象
然后通过System.arraycopy(oldstr,0,newstr,0,oldlength);
代码==============================================================
public static void main(String args[]){
int arr[] = {1,2,3};
int arr_new[] = (int[]) arrayInc(arr,5);
print(arr_new);
String str[] ={"Johnson","Gloryia","Roy"};
String str_new[] = (String[])arrayInc(str,8);
print(str_new);
}
public static Object arrayInc(Object obj,int len){
Class<?> c = obj.getClass().getComponentType();
Object obq = Array.newInstance(c, len);
System.arraycopy(obj,0,obq,0,Array.getLength(obj)) ; // 拷贝内容
return obq;
}
public static void print(Object obj){
System.out.println("数组类型为 " + obj.getClass().getComponentType().getName());
System.out.println("数组长度为 " + Array.getLength(obj));
for(int i=0;i<Array.getLength(obj);i++){
System.out.print(Array.get(obj,i) + " ");
}
}
5. 动态代理的实现
以前都是一个接口类对应一个接口实现类,一个代理类,然后一个main函数执行。
如果实现类较多的话,代理类也会越来越多,会引起代码的重复。
因此出现了动态代理,只写一个代理类实现invocationHandler接口即可,可以调用所有的接口实现类。
代码====================================================================
思路: 比如对于打印机,虽然实现的操作接口一样,但不同品牌的实现类有不同的实现方法。
如果按老的办法,在工程中就会需要申明不通的实现类对象,在需要调用的地方调用。
现在只需要写出来一个动态代理类,根据设备的需要,动态将不通品牌的实现类对象绑定,并执行其公共接口函数即可。
不只是不同品牌的打印机,甚至于读卡器、身份证识别器,也都可以用这个动态代理,绑定执行,代理程序在这里只有一份代码。
动态代理类 实现 InvocationHandler接口,一个是实现invoke函数,函数中用math对象调用invoke函数。
最重要是动态代理实现与实现类对象的绑定,band,主要是调用Proxy.newProxyInstance函数。
main函数中调用的主要就是 代理类对象.方法。
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
interface Subject{
public String say(String name,int age);
}
class RealSubject implements Subject{
public String say(String name,int age){
return "姓名 :" + name + " 年龄:"+ age;
}
}
class MyInvocationHandler implements InvocationHandler{
private Object obj;
public Object band(Object obj){
this.obj = obj; // 真实主题类
return Proxy.newProxyInstance(obj.getClass().getClassLoader() , obj.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
return method.invoke(this.obj,args); // 调用方法
}
}
public class DynaProxyDemo{
public static void main(String args[]){
Subject sub = (Subject) new MyInvocationHandler().band(new RealSubject());
System.out.println(sub.say("李柯",30));
}
}
6.工厂设计模式
主要为了以后新增其他品牌的设备,只需要按照接口,写这个设备的实现类即可。
另外,在配置文件中将该设备的实现类配上,即可连接改设备。
代码===================================================================
package org.lixh.demo15;
import java.util.Properties ;
import java.io.File ;
import java.io.FileOutputStream ;
import java.io.FileInputStream ;
interface Fruit{
public String getFruit();
}
class Apple implements Fruit{
public String getFruit(){
return "苹果";
}
}
class Banana implements Fruit{
public String getFruit(){
return "香蕉";
}
}
class Init{
public static Properties getPro(){
Properties pro = new Properties() ;
File f = new File("d:\\fruit.properties") ; // 找到属性文件
try{
if(f.exists()){ // 文件存在
pro.load(new FileInputStream(f)) ; // 读取属性
}else{
pro.setProperty("apple","org.lxh.demo15.factorydemo02.Apple") ;
pro.setProperty("orange","org.lxh.demo15.factorydemo02.Orange") ;
pro.store(new FileOutputStream(f),"FRUIT CLASS") ;
}
}catch(Exception e){}
return pro ;
}
};
class FactoryFruit{
public static Fruit getInstance(String className){
Fruit fr = null;
try{
fr = (Fruit)Class.forName(className).newInstance();
}catch (Exception e){
e.printStackTrace();
}
return fr;
}
}
public class FactoryDemo1{
public static void main(String args[]){
Properties pro = Init.getPro() ;
String temp = FactoryFruit.getInstance(pro.getProperty("apple")).getFruit();
System.out.println(temp);
}
}
JAVA 学习笔记 - 反射机制的更多相关文章
- Java学习笔记-反射机制
Java反射机制实在运行状态时,对于任意一个类,都能够知道这个类的属性和方法,对于任意一个对象,都能够调用他的任意一个属性和方法 获取Class对象的三种方式 Object类中的getClass()方 ...
- java学习之反射机制
java语言区别于C,C++等准静态语言的最大特点就是java的反射机制.静态语言的最直接定义就是不能在运行时改变程序结构或变量的类型.按照这样的定义,python,ruby是动态语言,C,C++,J ...
- 0032 Java学习笔记-类加载机制-初步
JVM虚拟机 Java虚拟机有自己完善的硬件架构(处理器.堆栈.寄存器等)和指令系统 Java虚拟机是一种能运行Java bytecode的虚拟机 JVM并非专属于Java语言,只要生成的编译文件能匹 ...
- java学习--Reflection反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制. ...
- Java学习:反射机制简介
反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法: 对于任意一个对象,都能够调用它的任意一个方法和属性: 这种动态获取的信息以及动态调用对象的方法的功能称为ja ...
- Java学习之反射机制及应用场景
前言: 最近公司正在进行业务组件化进程,其中的路由实现用到了Java的反射机制,既然用到了就想着好好学习总结一下,其实无论是之前的EventBus 2.x版本还是Retrofit.早期的View注解框 ...
- Java学习笔记--反射
什么是Java反射 概念 java反射是指java能够在运行时确定类的类型信息,包括其方法.字段.构造函数等,并能够通过反射调用类或者类对象的方法.在Java中,java.lang.Class类与ja ...
- Java 学习之反射机制“解刨”分解类,并获取内容!
正常情况下,单纯的做开发是接触不到反射机制的(额,当然并不排除例外的情况了).下面我就对我学到的反射方面的知识做一个小小的总结,旨在复习和以后的查看. 原理分析: 所谓反射就是将一个类当做我们研究的对 ...
- Java学习笔记--反射API
反射API 1.反射API的介绍 通过反射API可以获取Java程序在运行时刻的内部结构.比如Java类中包含的构造方法.域和方法等元素,并可以与这些元素进行交换. 按照 一般地面向对象的设计 ...
随机推荐
- 关于maven pom
1 maven pom.xml只是配置文件 构建的流程已经固化在maven中了,pom.xml只是对这个流程的配置.特别是插件,在不进行人工绑定的情况下,插件是对应固定的生命周期的,我们操作的时候是操 ...
- Element is not clickable at point SeleniumWebdriverException
Element is not clickable at point SeleniumWebdriverException | Selenium Easy http://www.seleniumeasy ...
- Hadoop Hive概念学习系列之hive里的索引(十三)
Hive支持索引,但是Hive的索引与关系型数据库中的索引并不相同,比如,Hive不支持主键或者外键. Hive索引可以建立在表中的某些列上,以提升一些操作的效率,例如减少MapReduce任务中需要 ...
- MTK 电池曲线配置【转】
本文转载自:http://blog.csdn.net/u010245383/article/details/51006597 硬件平台:MT8382 网上有很多关于电池曲线配置的文档,定位到具体的文件 ...
- hash与map的区别联系应用
一,hashtable原理: 哈希表又名散列表,其主要目的是用于解决数据的快速定位问题.考虑如下一个场景. 一列键值对数据,存储在一个table中,如何通过数据的关键字快速查找相应值呢?不要告诉我一个 ...
- vs2013/2015中scanf函数类似于error C4996: 'scanf': This function or variable may be unsafe的安全检查错误
在使用vs2015时,遇到了scnaf函数安全性的问题,程序不能正常运行,错误如下: error C4996: 'scanf': This function or variable may be un ...
- BZOJ_3479_[Usaco2014 Mar]Watering the Fields_Prim
BZOJ_3479_[Usaco2014 Mar]Watering the Fields_Prim Description Due to a lack of rain, Farmer John wan ...
- [Tjoi2016&Heoi2016] 树
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=4551 [算法] 树链剖分 时间复杂度 : O(QlogN) [代码] #includ ...
- java.util.Optional
public class OptionalDemo { public static void main(String[] args) { //创建Optional实例,也可以通过方法返回值得到. Op ...
- 【优化算法】Greedy Randomized Adaptive Search算法 超详细解析,附代码实现TSP问题求解
01 概述 Greedy Randomized Adaptive Search,贪婪随机自适应搜索(GRAS),是组合优化问题中的多起点元启发式算法,在算法的每次迭代中,主要由两个阶段组成:构造(co ...