Java反射机制研究

简介:

http://blog.csdn.net/jia635/article/details/39256187

以前听同时说反射很强大,看了一些相关文章今天把反射总结一下。

说明:反射主要用于开发框架,即制作框架;
一、获得Class对象

Class<?> c = Class.forName("classname");   抛出ClassNotFoundException


二、获得实现接口
Class<?> inters[] = c.getInterfaces();
for(int i=0;i<inters.length;i++){
    System.out.print(inters[i].getName()+" ");        //getName()方法为取得接口名称;
}

三、获得父类
Class<?> superClass  = c.getSuperclass();     //获得父类
String name  = superClass.getName();    //获得父类名称

四、取得构造方法
Constructor cons[] = c.getConstructors();         //获得公开的构造方法
Constructor dcons[] = c.getDeclaredConstructors();        //获得全部构造方法
String modifier = Modifier.toString(cons[i].getModifiers());   //获得访问权限
String name = cons[i].getName();            //获得构造方法名称
Class<?> params[] = cons[i].getParameterTypes();        //获得参数类型对象

五、获得Method
Method ms[] = c.getMethods();                        //返回公共的全部方法,包括继承方法
Method dms[] = c.getDeclaredMethods();        //返回本类全部方法,不包括继承的方法
Class<?> rt = ms[i].getReturnType();
Class<?>params[] = ms[i].getParameterTypes();
String name = ms[i].getName();
String modifier = Modifier.toString(ms[i].getModifiers());
Class<?>ex[] = ms[i].getExceptionTypes();        //获得异常
String name = ex[i].getName();            //获得异常名称

六、获得Field
Field fs[] = c.getFields();                    //获得公共属性,包括继承属性
Field dfs[] = c.getDeclaredFields();    // 获得本类全部属性
Class<?> type = fs[i].getType();        //获得属性的类型对象
String name = fs[i].getName();        //获得属性的名称
String modifier = Modifier.toString(fs[i].getModifiers());


七、通过反射创建一个对象
(1)
Class<?> c = Class.forName("Person");
Person p = (Person)c.newInstance();
(2)
Constructor con = c1.getConstructor(Class....param);
Object obj = con.newInstance(Object obj);  //根据构造函数创建一个实例

八、Constructor创建对象
Class c = Class.forName("Person");
Constructor<?> cons[] = c.getConstructors();
Person p = (Person)cons[0].newInstance("xiazdong",15);
注:如果调用的构造函数为私有,则需要c.setAccessible(true);


九、调用特定方法
Method m = c1.getMethod("funcname",Class<?>...c);   //funcname表示调用方法的名称,c表示参数的Class对象
例如:Method m = c1.getMethod("fun",String.class,int.class);    表示调用fun(String,int);函数
Object obj = m.invoke(c1.newInstance(),"xiazdong",20);   //如果有返回值,则invoke函数返回;
注:如果是调用静态的方法,则不需要设置对象;
Object obj = m.invoke(null,"xiazdong");

注:如果参数中有数组,比如 public static void main(String[]args);

Method m = c1.getMethod("main",String[].class);
m.invoke(null,(Object)new String[]{"aa","bb"});是对的;
m.invoke(null,new String[]{"aa","bb"}); 会调用 main(String,String);函数;

十、调用特定属性

Field f = c1.getDeclaredField("name");    //返回name属性
f.setAccessible(true);    //私有属性可见
String name = (String)f.get(Object obj);   //返回obj对象的name属性的值
f.set(Object obj,String n);      //设置obj对象的name属性为n值;


十一、操作数组
int tmp[] = {1,2,3};
Class<?> c  = tmp.getClass().getComponentType();
Array.getLength(tmp);        //tmp数组的长度
c.getName();           //获得数组类型名称
Array.get(Object obj,int index);      //获得obj数组的index索引的数值
Array.set(Object obj,int index,VALUE);    //设置obj数组的index索引的数值为value;
Object obj  = Array.newInstance(c,length);          //c为数组的类型,length为数组的长度;obj为返回的数组对象;
示例:

  1. import java.lang.reflect.*;  
  2. public class GetMethodDemo01{  
  3.     public static void main(String args[])throws Exception{  
  4.         Class<?> c1 = Class.forName("Person");  
  5.         Method m = c1.getMethod("sayHello");  
  6.         m.invoke(c1.newInstance());  
  7.         Method m2 = c1.getMethod("sayHello2",String.class,int.class);  
  8.         String str = (String)m2.invoke(c1.newInstance(),"xiazdong",123);  
  9.         System.out.println(str);  
  10.         Field nameField = c1.getDeclaredField("name");  
  11.         Field ageField = c1.getDeclaredField("age");  
  12.         nameField.setAccessible(true);  
  13.         ageField.setAccessible(true);  
  14.         Person obj = (Person)c1.newInstance();  
  15.         obj.setName("xzdong");  
  16.         obj.setAge(12);  
  17.         System.out.println(nameField.get(obj));  
  18.         System.out.println(ageField.get(obj));  
  19.         Method setName = c1.getMethod("setName",String.class);  
  20.         setName.invoke(obj,"changed");  
  21.         Method getName = c1.getMethod("getName");  
  22.         System.out.println(getName.invoke(obj));  
  23.   
  24.         int tmp[] = {1,2,3};  
  25.         Class<?> c3 = tmp.getClass().getComponentType();  
  26.         System.out.println(c3.getName());  
  27.         System.out.println("第一个数:"+Array.get(tmp,0));  
  28.         Array.set(tmp,0,5);  
  29.         System.out.println("第一个数:"+Array.get(tmp,0));  
  30.   
  31.         Object arr = Array.newInstance(c3,5);  
  32.         System.arraycopy(tmp,0,arr,0,Array.getLength(tmp));  
  33.         System.out.println(Array.get(arr,2));  
  34.         System.out.println(Array.get(arr,3));  
  35.     }  
  36. }  
import java.lang.reflect.*;
public class GetMethodDemo01{
	public static void main(String args[])throws Exception{
		Class<?> c1 = Class.forName("Person");
		Method m = c1.getMethod("sayHello");
		m.invoke(c1.newInstance());
		Method m2 = c1.getMethod("sayHello2",String.class,int.class);
		String str = (String)m2.invoke(c1.newInstance(),"xiazdong",123);
		System.out.println(str);
		Field nameField = c1.getDeclaredField("name");
		Field ageField = c1.getDeclaredField("age");
		nameField.setAccessible(true);
		ageField.setAccessible(true);
		Person obj = (Person)c1.newInstance();
		obj.setName("xzdong");
		obj.setAge(12);
		System.out.println(nameField.get(obj));
		System.out.println(ageField.get(obj));
		Method setName = c1.getMethod("setName",String.class);
		setName.invoke(obj,"changed");
		Method getName = c1.getMethod("getName");
		System.out.println(getName.invoke(obj));

		int tmp[] = {1,2,3};
		Class<?> c3 = tmp.getClass().getComponentType();
		System.out.println(c3.getName());
		System.out.println("第一个数:"+Array.get(tmp,0));
		Array.set(tmp,0,5);
		System.out.println("第一个数:"+Array.get(tmp,0));

		Object arr = Array.newInstance(c3,5);
		System.arraycopy(tmp,0,arr,0,Array.getLength(tmp));
		System.out.println(Array.get(arr,2));
		System.out.println(Array.get(arr,3));
	}
}


 

  1. import java.lang.reflect.*;  
  2. interface China{  
  3.     public static final String NAME = "CHINA";  
  4.     public int AGE = 60;  
  5.     public void sayHello();  
  6.     public String sayHello2(String name,int age);  
  7. }  
  8. class Person implements China{  
  9.     private String name;  
  10.     private int age;  
  11.     public String getName(){  
  12.         return name;  
  13.     }  
  14.     public void setName(String name){  
  15.         this.name = name;  
  16.     }  
  17.     public int getAge(){  
  18.         return age;  
  19.     }  
  20.     public void setAge(int age){  
  21.         this.age = age;  
  22.     }  
  23.     public void sayHello(){  
  24.         System.out.println(NAME+"  "+AGE);  
  25.     }  
  26.     public String sayHello2(String name,int age){  
  27.         return name+" "+age;  
  28.     }  
  29. }  
import java.lang.reflect.*;
interface China{
	public static final String NAME = "CHINA";
	public int AGE = 60;
	public void sayHello();
	public String sayHello2(String name,int age);
}
class Person implements China{
	private String name;
	private int age;
	public String getName(){
		return name;
	}
	public void setName(String name){
		this.name = name;
	}
	public int getAge(){
		return age;
	}
	public void setAge(int age){
		this.age = age;
	}
	public void sayHello(){
		System.out.println(NAME+"  "+AGE);
	}
	public String sayHello2(String name,int age){
		return name+" "+age;
	}
}


十一、工厂设计模式

1.最简单的工厂设计模式
场景:有一个Fruit接口,Apple类和Orange类都实现了Fruit接口,Factory用来生产水果;

  1. import java.io.*;  
  2. import java.util.*;  
  3.   
  4. interface Fruit{  
  5.     public void eat();  
  6. }  
  7. class Apple implements Fruit{  
  8.     public void eat(){  
  9.         System.out.println("吃苹果");  
  10.     }  
  11. }  
  12. class Orange implements Fruit{  
  13.     public void eat(){  
  14.         System.out.println("吃橘子");  
  15.     }  
  16. }  
  17. class Factory{  
  18.     public static Fruit getInstance(String name)throws Exception{  
  19.         Fruit f = null;  
  20.         if("apple".equals(name)){  
  21.             f = new Apple();  
  22.         }  
  23.         else if("orange".equals(name)){  
  24.             f = new Orange();  
  25.         }  
  26.         if(f!=null){  
  27.             return f;  
  28.         }  
  29.         else return null;  
  30.     }  
  31. }  
  32. public class FactoryDemo01{  
  33.     public static void main(String args[])throws Exception{  
  34.           
  35.         Fruit f = Factory.getInstance("apple");  
  36.         f.eat();  
  37.     }  
  38. }  
import java.io.*;
import java.util.*;

interface Fruit{
	public void eat();
}
class Apple implements Fruit{
	public void eat(){
		System.out.println("吃苹果");
	}
}
class Orange implements Fruit{
	public void eat(){
		System.out.println("吃橘子");
	}
}
class Factory{
	public static Fruit getInstance(String name)throws Exception{
		Fruit f = null;
		if("apple".equals(name)){
			f = new Apple();
		}
		else if("orange".equals(name)){
			f = new Orange();
		}
		if(f!=null){
			return f;
		}
		else return null;
	}
}
public class FactoryDemo01{
	public static void main(String args[])throws Exception{
		
		Fruit f = Factory.getInstance("apple");
		f.eat();
	}
}


2.通过反射实现
上面的例子有一个坏处,就是在Factory的getInstance代码会随着水果数量增加而增加,比如如果增加了一个banana类,则需要添加
if(name.equals("banana")){...}
这样非常不方便,因此反射就是一个很好的解决方法:

  1. import java.io.*;  
  2. import java.util.*;  
  3.   
  4. interface Fruit{  
  5.     public void eat();  
  6. }  
  7. class Apple implements Fruit{  
  8.     public void eat(){  
  9.         System.out.println("吃苹果");  
  10.     }  
  11. }  
  12. class Orange implements Fruit{  
  13.     public void eat(){  
  14.         System.out.println("吃橘子");  
  15.     }  
  16. }  
  17. class Factory{  
  18.     public static Fruit getInstance(String name)throws Exception{  
  19.         Fruit f = null  
  20.         Fruit f = (Fruit)Class.forName(name).newInstance();  
  21.         if(f!=null){  
  22.             return f;  
  23.         }  
  24.         else return null;  
  25.     }  
  26. }  
  27. public class FactoryDemo01{  
  28.     public static void main(String args[])throws Exception{  
  29.           
  30.         Fruit f = Factory.getInstance("Apple");  
  31.         f.eat();  
  32.     }  
  33. }  
import java.io.*;
import java.util.*;

interface Fruit{
	public void eat();
}
class Apple implements Fruit{
	public void eat(){
		System.out.println("吃苹果");
	}
}
class Orange implements Fruit{
	public void eat(){
		System.out.println("吃橘子");
	}
}
class Factory{
	public static Fruit getInstance(String name)throws Exception{
		Fruit f = null
		Fruit f = (Fruit)Class.forName(name).newInstance();
		if(f!=null){
			return f;
		}
		else return null;
	}
}
public class FactoryDemo01{
	public static void main(String args[])throws Exception{
		
		Fruit f = Factory.getInstance("Apple");
		f.eat();
	}
}

3.增加灵活性:配置文件

但是还有一个缺点,就是如果Apple类等有包名,则如果要访问此类,必须添加包名+类名称才可以。比如Apple类的最上方:package org;则必须通过org.Apple才可以访问Apple类。因此通过Properties文件可以解决这个问题;

  1. import java.io.*;  
  2. import java.util.*;  
  3.   
  4. interface Fruit{  
  5.     public void eat();  
  6. }  
  7. class Apple implements Fruit{  
  8.     public void eat(){  
  9.         System.out.println("吃苹果");  
  10.     }  
  11. }  
  12. class Orange implements Fruit{  
  13.     public void eat(){  
  14.         System.out.println("吃橘子");  
  15.     }  
  16. }  
  17. class Factory{  
  18.     public static Fruit getInstance(String name)throws Exception{  
  19.         Fruit f = null  
  20.         Fruit f = (Fruit)Class.forName(name).newInstance();  
  21.         if(f!=null){  
  22.             return f;  
  23.         }  
  24.         else return null;  
  25.     }  
  26.         private Factory(){}  
  27. }  
  28. public class FactoryDemo01{  
  29.     public static void main(String args[])throws Exception{  
  30.         Properties p = new Properties();  
  31.         p.load(new FileInputStream("1.properties"));  
  32.         String str = p.getProperty("apple");  
  33.         Fruit f = Factory.getInstance(str);  
  34.         f.eat();  
  35.     }  
  36. }  
import java.io.*;
import java.util.*;

interface Fruit{
	public void eat();
}
class Apple implements Fruit{
	public void eat(){
		System.out.println("吃苹果");
	}
}
class Orange implements Fruit{
	public void eat(){
		System.out.println("吃橘子");
	}
}
class Factory{
	public static Fruit getInstance(String name)throws Exception{
		Fruit f = null
		Fruit f = (Fruit)Class.forName(name).newInstance();
		if(f!=null){
			return f;
		}
		else return null;
	}
        private Factory(){}
}
public class FactoryDemo01{
	public static void main(String args[])throws Exception{
		Properties p = new Properties();
		p.load(new FileInputStream("1.properties"));
		String str = p.getProperty("apple");
		Fruit f = Factory.getInstance(str);
		f.eat();
	}
}


1.properties代码:

apple=Apple
orange=Orange


 

相关文章
|
5月前
|
设计模式 人工智能 安全
AQS:Java 中悲观锁的底层实现机制
AQS(AbstractQueuedSynchronizer)是Java并发包中实现同步组件的基础工具,支持锁(如ReentrantLock、ReadWriteLock)和线程同步工具类(如CountDownLatch、Semaphore)等。Doug Lea设计AQS旨在抽象基础同步操作,简化同步组件构建。 使用AQS需实现`tryAcquire(int arg)`和`tryRelease(int arg)`方法以获取和释放资源,共享模式还需实现`tryAcquireShared(int arg)`和`tryReleaseShared(int arg)`。
252 32
AQS:Java 中悲观锁的底层实现机制
|
3月前
|
人工智能 缓存 安全
Java中的反射机制:深入探索与应用
Java反射机制是程序运行时动态获取类信息并操作类成员的特性,具备高度灵活性,但也伴随性能与安全风险。本文详解反射的基本用法、高级应用及最佳实践,助你掌握这一强大工具的正确使用方式。
136 0
|
5月前
|
人工智能 Java 关系型数据库
Java——SPI机制详解
SPI(Service Provider Interface)是JDK内置的服务提供发现机制,主要用于框架扩展和组件替换。通过在`META-INF/services/`目录下定义接口实现类文件,Java程序可利用`ServiceLoader`动态加载服务实现。SPI核心思想是解耦,允许不同厂商为同一接口提供多种实现,如`java.sql.Driver`的MySQL与PostgreSQL实现。然而,SPI存在缺陷:需遍历所有实现并实例化,可能造成资源浪费;获取实现类方式不够灵活;多线程使用时存在安全问题。尽管如此,SPI仍是Java生态系统中实现插件化和模块化设计的重要工具。
159 0
|
3月前
|
人工智能 前端开发 安全
Java开发不可不知的秘密:类加载器实现机制
类加载器是Java中负责动态加载类到JVM的组件,理解其工作原理对开发复杂应用至关重要。本文详解类加载过程、双亲委派模型及常见类加载器,并介绍自定义类加载器的实现与应用场景。
186 4
|
3月前
|
人工智能 安全 Java
掌握Java反射:在项目中高效应用反射机制
Java反射是一种强大功能,允许程序在运行时动态获取类信息、创建对象、调用方法和访问字段,提升程序灵活性。它在框架开发、动态代理、注解处理等场景中广泛应用,如Spring和Hibernate。但反射也存在性能开销、安全风险和代码复杂性,应谨慎使用。
|
3月前
|
存储 监控 算法
企业上网监控场景下布隆过滤器的 Java 算法构建及其性能优化研究
布隆过滤器是一种高效的数据结构,广泛应用于企业上网监控系统中,用于快速判断员工访问的网址是否为违规站点。相比传统哈希表,它具有更低的内存占用和更快的查询速度,支持实时拦截、动态更新和资源压缩,有效提升系统性能并降低成本。
73 0
|
4月前
|
人工智能 Java
Java中的反射机制:深入探索与应用
本文介绍了Java反射机制的基本概念、用途及其实现方式。反射机制允许程序在运行时动态获取类的属性和方法,并调用它们,适用于处理私有成员或权限受限的情况。文章详细讲解了`Class`类的功能,包括获取类的方法、属性、注解、构造器等信息,以及通过四种方式获取`Class`对象的示例代码。此外,还探讨了类加载器、继承关系判断、动态代理等高级内容,展示了如何在运行时创建接口实例并处理方法调用。文末提供了完整的代码示例以加深理解。
Java中的反射机制:深入探索与应用
|
5月前
|
Java 区块链 网络架构
酷阿鲸森林农场:Java 区块链系统中的 P2P 区块同步与节点自动加入机制
本文介绍了基于 Java 的去中心化区块链电商系统设计与实现,重点探讨了 P2P 网络在酷阿鲸森林农场项目中的应用。通过节点自动发现、区块广播同步及链校验功能,系统实现了无需中心服务器的点对点网络架构。文章详细解析了核心代码逻辑,包括 P2P 服务端监听、客户端广播新区块及节点列表自动获取等环节,并提出了消息签名验证、WebSocket 替代 Socket 等优化方向。该系统不仅适用于农业电商,还可扩展至教育、物流等领域,构建可信数据链条。
|
5月前
|
人工智能 JavaScript Java
Java反射机制及原理
本文介绍了Java反射机制的基本概念、使用方法及其原理。反射在实际项目中比代理更常用,掌握它可以提升编程能力并理解框架设计原理。文章详细讲解了获取Class对象的四种方式:对象.getClass()、类.class、Class.forName()和类加载器.loadClass(),并分析了Class.forName()与ClassLoader的区别。此外,还探讨了通过Class对象进行实例化、获取方法和字段等操作的具体实现。最后从JVM类加载机制角度解析了Class对象的本质及其与类和实例的关系,帮助读者深入理解Java反射的工作原理。
104 0
|
7月前
|
缓存 Dubbo Java
理解的Java中SPI机制
本文深入解析了JDK提供的Java SPI(Service Provider Interface)机制,这是一种基于接口编程、策略模式与配置文件组合实现的动态加载机制,核心在于解耦。文章通过具体示例介绍了SPI的使用方法,包括定义接口、创建配置文件及加载实现类的过程,并分析了其原理与优缺点。SPI适用于框架扩展或替换场景,如JDBC驱动加载、SLF4J日志实现等,但存在加载效率低和线程安全问题。
279 7
理解的Java中SPI机制