Java知识总结:Java反射机制(用实例理解)
概念理解:
反射是指一类应用,它们能够自描述和自控制。也就是说,这类应用通过采用某种机制来 实现对自己行为的描述( self-representation )和检测( examination) ,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。
Java中的反射是一个强大的工具,他能够创建灵活的代码,这些 代码可以在运行时装配,无需在组件之间进行链接,发射允许在编写和执行时,使程序代码能够接入装载到 JVM 中的类的内部信息 。而不是源代码中选定的类协作的代码。这使发射成为构建灵活运用的主要工具。值得注意是,如果使用不当,发射的成本会更高。
Java中的类的反射Refection是Java程序开发语言的特征之一,它允许运行中的Java程度对自身进行检查,或者说“自审”,并能直接操作程序的内部属性。Java的这一能力在实际应用中也许用的不是很多,但是在其他的程序设计语言中,根本就不存在这样的特性,例如:Pascal、C或者C++中就没有办法在程序中获得与函数定义相关的信息。
案例理解 Java 反射机制:
【案例 1 】 通过一个对象获得完整的包名和类名
package com.guan.goodboy;
public class Demo {
public Demo(){
}
}
package com.guan.goodboy;
public class FiveHead {
public static void main(String[] args) {
Demo demo = new Demo();
System. out .println(demo.getClass().getName());
}
}
【运行结果】 : com.guan.goodboy.Demo
注解:所有类的对象其实都是 Class 的实例。
【案例 2 】 实例化 Class 类对象(三种方法)
方法一 : Class. forName ( "com.guan.goodboy.Demo" );
方法二 : new Demo().getClass();
方法三 : new Demo().getClass();
package com.guan.goodboy;
public class Demo {
public Demo(){
}
}
package com.guan.goodboy;
public class FiveHead {
public static void main(String[] args) {
Class<?> demo1= null ;
Class<?> demo2= null ;
Class<?> demo3= null ;
try {
// 一般尽量采用这种形式
// 调用 Class 的静态方法,将包名下的类 Foo 加载到 JVM (虚拟机)的方法区中
demo1=Class. forName ( "com.guan.goodboy.Demo" );
} catch (Exception e){
e.printStackTrace();
}
demo2= new Demo().getClass();
demo3=Demo. class ;
System. out .println( " 类名称 " +demo1.getName());
System. out .println( " 类名称 " +demo2.getName());
System. out .println( " 类名称 " +demo3.getName());
}
}
【运行结果】 :
类名称 com.guan.goodboy.Demo
类名称 com.guan.goodboy.Demo
类名称 com.guan.goodboy.Demo
【案例 3 】 : 通过 Class 实例化其他类的对象
package com.guan.goodboy;
public class Person {
public String getName() {
return name ;
}
public void setName(Stringname) {
this . name = name;
}
public int getAge() {
return age ;
}
public void setAge( int age) {
this . age = age;
}
@Override
public String toString(){
return "[" + this . name + " " + this . age + "]" ;
}
private String name ;
private int age ;
}
package com.guan.goodboy;
public class FiveHead {
public static void main(String[] args) {
Class<?> demo= null ;
try {
// 调用 Class 的静态方法,将包名下的类 Foo 加载到 JVM (虚拟机)的方法区中
demo=Class. forName ( "com.guan.goodboy.Person" );
} catch (Exception e) {
e.printStackTrace();
}
Person per= null ;
try {
// 通过反射,实例化对象,创建一个无参数的构造器(反射机制)
per=(Person)demo.newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
per.setName( "Rollen" );
per.setAge(20);
System. out .println(per);
}
}
【运行结果】 : [Rollen 20]
注意: 当我们把 Person 中的默认的无参构造函数取消的时候,比如自己定义只定义一个有参数的构造函数之后,会出现错误:
比如我定义了一个构造函数:
public Person(String name, int age) {
this . age =age;
this . name =name;
}
然后继续运行上面的程序,会出现:
java.lang.InstantiationException : com.guan.goodboy.Person
at java.lang.Class.newInstance0( Class.java:357 )
at java.lang.Class.newInstance( Class.java:325 )
at com.guan.goodboy.FiveHead.main( FiveHead.java:15 )
Exception inthread "main" java.lang.NullPointerException
at com.guan.goodboy.FiveHead.main( FiveHead.java:23 )
所以大家以后再编写使用Class实例化其他类的对象的时候, 一定要自己定义无参的构造函数(很重要)
【案例 4 】 通过Class调用其他类中的构造函数 (也可以通过这种方式通过Class创建其他类的对象)
package com.guan.goodboy;
public class Person {
private String name ;
private int age ;
public Person() {
}
public Person(String name){
this . name =name;
}
public Person( int age ){
this . age = age ;
}
public Person(String name, int age) {
this . age =age;
this . name =name;
}
public String getName() {
return name ;
}
public int getAge() {
return age ;
}
@Override
public String toString(){
return "[" + this . name + " " + this . age + "]" ;
}
}
package com.guan.goodboy;
import java.lang.reflect.Constructor;
public class FiveHead {
public static void main(String[] args) {
Class<?> demo= null ;
try {
// 调用 Class 的静态方法,将包名下的类 Foo 加载到 JVM (虚拟机)的方法区中
demo=Class. forName ( "com.guan.goodboy.Person" );
} catch (Exception e) {
e.printStackTrace();
}
Person per1= null ;
Person per2= null ;
Person per3= null ;
Person per4= null ;
// 取得全部的构造函数
Constructor<?>cons[]=demo.getConstructors();
// 检测一个奇怪的现象,就是构造器的生成时从后面算起的
System. out .println(cons[0]);
System. out .println(cons[1]);
System. out .println(cons[2]);
System. out .println(cons[3]);
System. out .println();
try {
// 获得的构造器,在进行参数赋值的时候,要与生成的构造器参数类型一直,不然会包如下错误
//java.lang.IllegalArgumentException: wrong number ofarguments
per1=(Person)cons[0].newInstance( "Rollen" ,20);
per2=(Person)cons[1].newInstance(20);
per3=(Person)cons[2].newInstance( "Rollen" );
per4=(Person)cons[3].newInstance();
} catch (Exception e){
e.printStackTrace();
}
System. out .println(per1);
System. out .println(per2);
System. out .println(per3);
System. out .println(per4);
}
}
【运行结果】:
publiccom.guan.goodboy.Person(java.lang.String,int)
publiccom.guan.goodboy.Person(int)
publiccom.guan.goodboy.Person(java.lang.String)
publiccom.guan.goodboy.Person()
[Rollen 20]
[null 20]
[Rollen 0]
[null 0]
【案例 5 】 通过Class调用其他类中的构造函数 (为了避免案例4中的顺序问题,可以通过构造器中的参数,指定相应的构成函数,如本例所示)
package com.guan.goodboy;
public class Person {
private String name ;
private Integer age ;
public Person() {
}
public Person(String name){
this . name =name;
}
public Person(Integer age){
this . age =age;
}
public Person(String name, Integer age) {
this . age =age;
this . name =name;
}
public String getName() {
return name ;
}
public int getAge() {
return age ;
}
@ Override
public String toString(){
return "[" + this . name + " " + this . age + "]" ;
}
}
package com.guan.goodboy;
import java.lang.reflect.Constructor;
public class FiveHead {
public static void main(String[] args) throws NoSuchMethodException, SecurityException {
Class<?> demo= null ;
try {
// 调用 Class 的静态方法,将包名下的类 Foo 加载到 JVM (虚拟机)的方法区中
demo=Class. forName ( "com.guan.goodboy.Person" );
} catch (Exception e) {
e.printStackTrace();
}
Person per1= null ;
Person per2= null ;
Person per3= null ;
Person per4= null ;
Constructor<?> con1 =demo.getConstructor( new Class[]{});
Constructor<?> con2 =demo.getConstructor( new Class[]{Integer. class });
Constructor<?> con3 = demo.getConstructor( new Class[]{String. class ,Integer.class });
Constructor<?> con4 =demo.getConstructor( new Class[]{String. class });
// 检测一个奇怪的现象,就是构造器的生成时从后面算起的
System. out .println(con1);
System. out .println(con2);
System. out .println(con3);
System. out .println(con4);
System. out .println();
try {
per1= (Person)con1.newInstance();
per2 = (Person)con2.newInstance( new Object[]{20});
per3= (Person)con3.newInstance( new Object[]{ "xiaoguan" ,20});
per4= (Person)con4.newInstance( new Object[]{ "xiaoguan" });
} catch (Exception e){
e.printStackTrace();
}
System. out .println(per1);
System. out .println(per2);
System. out .println(per3);
System. out .println(per4);
}
}
【运行结果】:
publiccom.guan.goodboy.Person()
publiccom.guan.goodboy.Person(java.lang.Integer)
publiccom.guan.goodboy.Person(java.lang.String,java.lang.Integer)
publiccom.guan.goodboy.Person(java.lang.String)
[null null]
[null 20]
[xiaoguan 20]
[xiaoguan null]
【案例 6 】 返回一个类实现的接口
package com.guan.goodboy;
interface China {
public static final String name = "Rollen" ;
public static int age =20;
public void sayChina();
public void sayHello(String name, int age);
}
package com.guan.goodboy;
public class Person implements China{
public Person() {
}
public Person(String sex){
this . sex =sex;
}
public String getSex() {
return sex ;
}
public void setSex(String sex) {
this . sex = sex;
}
public void sayChina(){
System. out .println( "hello ,china" );
}
public void sayHello(String name, int age){
System. out .println(name+ " " +age);
}
private String sex ;
}
package com.guan.goodboy;
public class FiveHead {
public static void main(String[] args) {
Class<?> demo= null ;
try {
demo=Class. forName ( "com.guan.goodboy.Person" );
} catch (Exception e) {
e.printStackTrace();
}
// 保存所有的接口
Class<?>intes[]=demo.getInterfaces();
for ( int i = 0; i <intes. length ; i++) {
System. out .println( " 实现的接口 " +intes[i].getName());
}
}
}
【运行结果】:
实现的接口 com.guan.goodboy.China
【案例 7 】取得其他类中的父类(下面几个案例,重用案例 6 的 Person 类和 China类,不再累述,现在只摘录主函数类,请看继续往下看)
package com.guan.goodboy;
public class FiveHead {
public static void main(String[] args) {
Class<?> demo= null ;
try {
demo=Class. forName ( "com.guan.goodboy.Person" );
} catch (Exception e) {
e.printStackTrace();
}
// 取得父类
Class<?>temp=demo.getSuperclass();
System. out .println( " 继承的父类为: " +temp.getName());
}
}
【运行结果】:
继承的父类为: java.lang.Object
【案例 8 】获得其他类中的全部构造函数(本案例,重用案例 6 的 Person 类和China 类,不再累述,现在只摘录主函数类,请看继续往下看)
package com.guan.goodboy;
import java.lang.reflect.Constructor;
public class FiveHead {
public static void main(String[] args) {
Class<?> demo= null ;
try {
demo=Class. forName ( "com.guan.goodboy.Person" );
} catch ( Exception e) {
e.printStackTrace();
}
Constructor<?>cons[]=demo.getConstructors();
for ( int i = 0; i <cons. length ; i++) {
System. out .println( " 构造方法: " +cons[i]);
}
}
}
【运行结果】:
构造方法: public com.guan.goodboy.Person()
构造方法: publiccom.guan.goodboy.Person(java.lang.String)
【案例 9 】获取构造函数中 public 或者 private 等这一类的修饰符(本案例,重用案例 6 的 Person 类和 China 类,不再累述,现在只摘录主函数类,请看继续往下看)
package com.guan.goodboy;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class FiveHead {
public static void main(String[] args) {
Class<?> demo= null ;
try {
demo=Class. forName ( "com.guan.goodboy.Person" );
} catch (Exception e) {
e.printStackTrace();
}
Constructor<?>cons[]=demo.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( "){}" );
}
}
}
【运行结果】:
构造方法: public com.guan.goodboy.Person(){}
构造方法: public com.guan.goodboy.Person(java.lang.String arg1){}
【案例 10 】获得类中所有方法及方法后的异常信息(本案例,重用案例 6 的Person 类和 China 类,不再累述,现在只摘录主函数类,请看继续往下看)
package com.guan.goodboy;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class FiveHead {
public static void main(String[] args) {
Class<?> demo= null ;
try {
demo=Class. forName ( "com.guan.goodboy.Person" );
} catch (Exception e) {
e.printStackTrace();
}
Method method[]=demo.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();
}
}
}
【运行结果】:
publicjava.lang.String getSex ()
publicvoid setSex (java.lang.String arg0)
publicvoid sayChina ()
publicvoid sayHello (java.lang.String arg0,intarg1)
public finalvoid wait () throws java.lang.InterruptedException
public finalvoid wait (long arg0,int arg1) throws java.lang.InterruptedException
public finalnative void wait (long arg0) throws java.lang.InterruptedException
publicboolean equals (java.lang.Object arg0)
publicjava.lang.String toString ()
publicnative int hashCode ()
public finalnative java.lang.Class getClass ()
public finalnative void notify ()
public finalnative void notifyAll ()
【案例 11 】接下来让我们取得其他类的全部属性吧,最后将这些整理在一起,也就是通过 class 取得一个类的全部框架(本案例,重用案例 6 的 Person 类和 China 类,不再累述,现在只摘录主函数类,请看继续往下看)
package com.guan.goodboy;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class FiveHead {
public static void main(String[] args) {
Class<?> demo = null ;
try {
demo = Class. forName ( "com.guan.goodboy.Person" );
} catch (Exception e) {
e.printStackTrace();
}
System. out .println( "=============== 本类属性========================" );
// 取得本类的全部属性
Field[] field = demo. 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 = demo.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() + ";" );
}
}
}
【运行结果】:
===============本类属性========================
privatejava.lang.String sex;
===============实现的接口或者父类的属性========================
publicstatic final java.lang.String name;
publicstatic final int age;
【案例 12 】通过反射调用其他类中的方法(本案例,重用案例 6 的 Person 类和China 类,不再累述,现在只摘录主函数类,请看继续往下看)
package com.guan.goodboy;
import java.lang.reflect.Method;
public class FiveHead {
public static void main(String[] args) {
Class<?> demo = null ;
try {
demo = Class. forName ( "com.guan.goodboy.Person" );
} catch (Exception e) {
e.printStackTrace();
}
try {
// 调用 Person 类中的 sayChina 方法
Methodmethod=demo.getMethod( "sayChina" );
System. out .println(method); // 输出结果如下
//public void com.guan.goodboy.Person.sayChina()
method.invoke(demo.newInstance());
// 调用 Person 的 sayHello 方法
method=demo.getMethod( "sayHello" , String. class , int . class );
method.invoke(demo.newInstance(), "Rollen" ,20);
} catch (Exception e) {
e.printStackTrace();
}
}
}
【运行结果】:
public voidcom.guan.goodboy.Person.sayChina()
hello ,china
Rollen 20
【 案例 13 】调用其它类的 get 与 set 方法(本案例,重用案例 6 的 Person 类和China 类,不再累述,现在只摘录主函数类,请看继续往下看)
package com.guan.goodboy;
import java.lang.reflect.Method;
public class FiveHead {
public static void main(String[] args) {
Class<?> demo = null ;
Object obj= null ;
try {
demo = Class. forName ( "com.guan.goodboy.Person" );
} catch (Exception e) {
e.printStackTrace();
}
try {
obj=demo.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
setter (obj, "Sex" , " 男 " ,String. class );
getter (obj, "Sex" );
}
/**
* @param obj
* 操作的对象
* @param att
* 操作的属性
* */
public static void getter(Object obj , String att) {
try {
Method method = obj .getClass().getMethod( "get" + att);
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) {
try {
Method method =obj.getClass().getMethod( "set" + att, type);
method.invoke(obj, value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
【运行结果】:
男
【案例 14 】通过反射操作属性(本案例,重用案例 6 的 Person 类和 China 类,不再累述,现在只摘录主函数类,请看继续往下看)
package com.guan.goodboy;
import java.lang.reflect.Field;
public class FiveHead {
public static void main(String[] args) throwsClassNotFoundException,InstantiationException, IllegalAccessException, NoSuchFieldException,SecurityException {
Class<?> demo = null ;
Object obj = null ;
demo = Class. forName ( "com.guan.goodboy.Person" );
obj = demo.newInstance();
Field field = demo.getDeclaredField( "sex" );
field.setAccessible( true );
field.set(obj, " 男 " );
System. out .println(field.get(obj));
}
}
【运行结果】:
男
【案例 15 】通过反射取得并修改数组的信息
package com.guan.goodboy;
import java.lang.reflect.Array ;
public class FiveHead {
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));
}
}
【运行结果】:
数组类型: int
数组长度 5
数组的第一个元素: 1
修改之后数组第一个元素为: 100
【案例 16 】通过反射修改数组大小
package com.guan.goodboy;
import java.lang.reflect.Array;
public class FiveHead {
public static void main(String[] args) {
int [] temp={1,2,3,4,5,6,7,8,9};
int [] newTemp=( int []) arrayInc (temp,15);
print (newTemp);
System. out .println();
System. out .println( "=====================" );
String[] atr={ "a" , "b" , "c" };
String[] str1=(String[]) arrayInc (atr,8);
print (str1);
}
/**
* 修改数组大小
* */
public static Object arrayInc(Object obj, int len){
Class<?>arr=obj.getClass().getComponentType();
Object newArr=Array. newInstance (arr,len);
int co=Array. getLength (obj);
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)+ " " );
}
}
}
【运行结果】:
数组长度为: 15
1 2 3 4 5 6 7 8 9 0 0 0 0 0 0
=====================
数组长度为: 8
a b c null null null null null
反射机制之动态代理:
【案例 17 】首先来看看如何获得类加载器:
package com.guan.goodboy;
public class Test {
}
package com.guan.goodboy;
public class FiveHead {
public static void main(String[] args) {
Test t= new Test();
System. out . println (t.getClass());
System. out . println (t.getClass().getClassLoader());
System. out . println (t.getClass().getClassLoader().getClass());
System. out .println( " 类加载器 "+t.getClass().getClassLoader().getClass().getName());
}
}
【运行结果】:
class com.guan.goodboy.Test
sun.misc.Launcher$AppClassLoader@2760e8a2
classsun.misc.Launcher$AppClassLoader
类加载器 sun.misc.Launcher$AppClassLoader
其实在 java 中有三种类类加载器。
1 )、 BootstrapClassLoader 此加载器采用 c++ 编写,一般开发中很少见。
2 )、 ExtensionClassLoader 用来进行扩展类的加载,一般对应的是 jre\lib\ext目录中的类
3 )、 AppClassLoader 加载 classpath 指定的类,是最常用的加载器。同时也是java 中默认的加载器。
【案例 18 】如果想要完成动态代理,首先需要定义一个 InvocationHandler 接口的子类,已完成代理的具体操作
package com.guan.goodboy;
/**
* 定义项目接口
*/
interface Subject {
public String say(String name, int age);
}
package com.guan.goodboy;
/**
* 定义真实项目
*/
class RealSubject implements Subject {
public String say(String name, int age) {
return name + " " + age;
}
}
package com.guan.goodboy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
class MyInvocationHandler implements InvocationHandler {
private Object obj = null ;
public Object bind(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 {
Object temp = method.invoke( this . obj , args);
return temp;
}
}
package com.guan.goodboy;
public class FiveHead {
public static void main(String[] args) {
MyInvocationHandler demo = new MyInvocationHandler();
Subject sub = (Subject) demo.bind( new RealSubject());
String info = sub.say( "Rollen" , 20);
System. out .println(info);
}
}
【运行结果】:
Rollen 20
类的生命周期
在一个类编译完成之后,下一步就需要开始使用类,如果要使用一个类,肯定离不开 JVM 。在程序执行中 JVM 通过 装载 , 链接 , 初始化 这 3 个步骤完成。
类的 装载 是通过类加载器完成的,加载器将 .class 文件的二进制文件装入 JVM 的方法区,并且在堆区创建描述这个类的 java.lang.Class 对象。用来封装数据。但是同一个类只会被类装载器装载,以前 链接 就是把二进制数据组装为可以运行的状态。
链接 分为校验,准备,解析这 3 个阶段
校验 一般用来确认此二进制文件是否适合当前的 JVM (版本),
准备 就是为静态成员分配内存空间,。并设置默认值
解析 指的是转换常量池中的代码作为直接引用的过程,直到所有的符号引用都可以被运行程序使用(建立完整的对应关系)
完成之后,类型也就完成了初始化,初始化之后类的对象就可以正常使用了,直到一个对象不再使用之后,将被垃圾回收。释放空间。
当没有任何引用指向 Class 对象时就会被卸载,结束类的生命周期
将反射用于工厂模式
先来看看,如果不用反射的时候,就用工厂模式吧:
http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144851.html
【案例 19 】现在来看看工厂模式
工厂模式特点: 当我们在添加一个子类的时候,就需要修改工厂类了。如果我们添加太多的子类的时候,改的就会很多。 【案例 20 】 用反射机制设置,请看 【案例 20】 .
package com.guan.goodboy;
/**
* 工厂模式设计
*/
interface Fruit{
public abstract void eat();
}
package com.guan.goodboy;
/**
* Apple 实现接口 Fruit
*/
class Apple implements Fruit{
public void eat(){
System. out .println( "Apple" );
}
}
package com.guan.goodboy;
/**
* Orange 实现接口 Fruit
*/
class Orange implements Fruit {
public void eat (){
System. out .println( "Orange" );
}
}
package com.guan.goodboy;
/**
* 构造工厂类
* 也就是说以后如果我们在添加其他的实例的时候只需要修改工厂类就行了
*/
class Factory{
public static Fruit getInstance(String fruitName ){
Fruit f= null ;
if ( "Apple" .equals( fruitName )){
f= new Apple();
}
if ( "Orange" .equals( fruitName )){
f= new Orange();
}
return f;
}
}
package com.guan.goodboy;
public class FiveHead {
public static void main(String[] args) {
Fruit f=Factory. getInstance ( "Orange" );
f.eat();
}
}
【运行结果】:
Orange
【案例 20 】用反射模式,实现 【案例 19 】 中同样的功能,请查看各自的区别(注解:其中主要的不同在 Factory 类与 main 函数类的不同)
package com.guan.goodboy;
/**
* Fruit 接口
*/
interface Fruit{
public abstract void eat();
}
package com.guan.goodboy;
/**
* Apple 实现接口 Fruit
*/
class Apple implements Fruit{
public void eat(){
System. out .println( "Apple" );
}
}
package com.guan.goodboy;
/**
* Orange 实现接口 Fruit
*/
class Orange implements Fruit{
public void eat(){
System. out .println( "Orange" );
}
}
package com.guan.goodboy;
/**
* 构造工厂类
* 也就是说以后如果我们在添加其他的实例的时候只需要修改工厂类就行了
*/
class Factory{
public static Fruit getInstance(String ClassName ){
Fruit f= null ;
try {
f=(Fruit)Class. forName ( ClassName ).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return f;
}
}
package com.guan.goodboy;
public class FiveHead {
public static void main(String[] args) {
Fruit f=Factory. getInstance ( "com.guan.goodboy.Apple" );
if (f!= null ){
f.eat();
}
}
}
【运行结果】:
Apple
参考文献:
编译工具Myeclipse8.6
JDK1.7
《Java编程思想》
《Java面试宝典》
http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html
http://blog.csdn.net/justinavril/article/details/2873664
http://zh.wikipedia.org/wiki/%E7%BC%96%E7%A8%8B%E8%8C%83%E5%9E%8B
Java知识总结:Java反射机制(用实例理解)的更多相关文章
- Java 核心类库之反射机制
1:什么是反射机制? 2:反射机制它可以做什么呢? 3:反射机制对应的API又是什么? 1):通过反射机制来获取一个对象的全限定名称(完整包名),和类名: 2):实例化Class对象 3):获取对象的 ...
- java 反射机制的实例
[案例1]通过一个对象获得完整的包名和类名 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package Reflect; /** * 通过一个对象获得完整的包名和类名 ...
- java反射机制简单实例
目录 Java反射 简单实例 @(目录) Java反射 Java语言允许通过程序化的方式间接对Class进行操作.Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通 ...
- Java开发培训基础知识解析之反射机制
Java是老牌编程语言,是当前应用最广泛的编程语言之一.想要学习Java你就一定要掌握Java基础知识,而反射对于初学Java的人来说绝对是非常重要的知识点.什么是反射?如何理解反射机制?如何使用反射 ...
- 在JAVA中,关于反射机制的讨论
一.什么是反射机制 简单的来说,反射机制指的是程序在运行时能够获取自身的信息.在java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息. 二.哪里用到反射机制 ...
- Java SE之初探反射机制
[Keywords]:Java,Hibernate,虚拟机,框架,SQL [Abstract]: 反射的概念:所谓的反射就是java语言在运行时拥有一项自观的能力,反射使您的程序代码能够得到装载到 ...
- Java进阶之reflection(反射机制)——反射概念与基础
反射机制是Java动态性之一,而说到动态性首先得了解动态语言.那么何为动态语言? 一.动态语言 动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化.比如常见 ...
- java工厂类与反射机制
java 简单工厂类 2012-04-22 15:44:07| 分类: java | 标签:java工厂类 简单工厂类 |举报|字号 订阅 简单工厂模式需要由以下角色组成: 接口 ...
- JAVA(五)反射机制/Annotation
成鹏致远 | lcw.cnblog.com |2014-02-04 反射机制 1.认识Class类 在正常情况下,必须知道一个类的完整路径之后才可以实例化对象,但是在 java中也允许通过一个对象来找 ...
- java.lang.Class<T> -- 反射机制及动态代理
Interface : Person package java_.lang_.component.bean; public interface Person { String area = " ...
随机推荐
- 一个Log-Tan积分
\[\Large\int_{0}^{\pi }\theta \ln\tan\frac{\theta }{2}\mathrm{d}\theta \] \(\Large\mathbf{Solution:} ...
- 高次arccos积分
\[\Large\displaystyle \int_0^{1} \frac{\arccos^4 \left(x^2\right)}{\sqrt{1-x^2}}\,\mathrm{d}x\] \(\L ...
- P1428
AC: #include <stdio.h> #define rep(i, a, b) for(int i = a; i <= b; i++) #define min(a, b) ( ...
- idea中使用Autowired注入时报红,但是运行不报错
在Preferences中如下设置,即可解除报红错误: 将Autowiring for Bean Class的Severity级别设置为Warning
- redis的使用1
学Linux已经将近一个月了,Linux中讲到的redis的使用,到现在还不回具体的使用在php中,今天周末,于是想把redis的使用搞懂. 网上的资料不算多,但还需要硬着头皮学.其中找到这样一篇关于 ...
- windows10 通过ssh访问 linux
安装openssh服务 Win10其实自带OpenSSH 没有的话,点击上面的添加找到并安装 在服务里设置对应服务开机启动 添加服务器到已知主机 ssh-keygen -R 你的服务器ip 连接Lin ...
- 【代码总结】PHP之会话跟踪技术
有些时候感觉自己学习的效率好低,一套教程一本书,反复听,反复看,反复敲代码.自学这条路真的是很艰难,在任何事情都没有成功之前都很枯燥乏味.自学的过程中总会遇到很多问题,有时候连错误的原因都找不出来,那 ...
- ubuntu 修改和配置ip
因为主机里面有好多个虚拟机,但是ip就一个,最近开了一个win的虚拟机,真好玩是不?所以就暂时把ubunut的ip给改了,要不冲突,哎呀,不说多了,上图, 1.修改配置文件blacklist.conf ...
- Card Game for Three
Alice, Bob and Charlie are playing Card Game for Three, as below: At first, each of the three player ...
- 吴裕雄--天生自然Numpy库学习笔记:NumPy 字节交换
大端模式:指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放 小端模式:指数据的高字节保 ...