`
香菇菌
  • 浏览: 957 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

JAVA 反射机制详解

阅读更多

      JAVA中万事万物皆为对象,包括类也是对象!所有的类都是java.lang.Class这个类的对象! 不信你可以随便选一个类测试一下, 我选java.lang.String为例  String类有一个静态成员变量class  通过该成员变量我们可以得到 Class c = String.class   即:String类型是这个Class类的一个对象  官方称这个对象c为String的类类型(class type)  同理 所有的类型与String一样

下面看我们如何创建某个类的类类型呢? 有三种方式:

比如说我们现在有个类叫做ReflectTest  

1、Class c1 = ReflectTest.class; //通过类的静态成员变量

2、Class c2 = new ReflectTest().getClass(); //调用该类的对象的getClass方法

3、Class c3 = Class.forName("com.xue.reflect.ReflectTest"); //通过Class类型的一个静态方法

每个类的类类型只有一个!!! 也就是说c1 == c2 == c3

还可以给类类型加上泛型:

Class<ReflectTest> c4 = ReflectTest.class;

可以通过类的类类型实例化该类的对象:

ReflectTest r = (ReflectTest) c1.newInstance();//这边要进行强制转换!除非前面创建类类型的时候指定了泛型就不用强制转换了

 

完整代码如下:

package com.xue.reflect;

 

public class ReflectTest {

 

 

 

 

public static void main(String[] args) {

Class c1 = ReflectTest.class;

Class c2 = new ReflectTest().getClass();

Class<ReflectTest> c4 = ReflectTest.class;

try {

Class c3 = Class.forName("com.xue.reflect.ReflectTest");

System.out.println("c1 == c3?:"+(c1 == c3));

} catch (ClassNotFoundException e) {

 

e.printStackTrace();

}

System.out.println("c1 == c2?:" + (c1 == c2));

 

try {

ReflectTest r = (ReflectTest) c1.newInstance();

r.toString();

ReflectTest r1 = c4.newInstance();

System.out.println(r1.toString());

} catch (InstantiationException e) {

 

e.printStackTrace();

} catch (IllegalAccessException e) {

 

e.printStackTrace();

}

 

}

 

 

@Override

public String toString() {

String s = "I am ReflectTest Class";

return s;

}

 

}

 

 

 

我们还可以通过Class.forName("类全称") 动态加载类, 这样的好处就是编译的时候不用静态加载所有的类

 

代码如下  我们先写一个Animal 接口:

package com.xue.reflect;

 

public interface Animal {

   

public void call();

}

 

 

然后再写2个实现类 分别是Tiger.java  和  Miao.java

 

Tiger.java :

package com.xue.reflect;

 

public class Tiger implements Animal {

@Override

public void call() {

System.out.println("哇~吼");

}

 

}

Miao.java:

package com.xue.reflect;

 

public class Miao implements Animal {

@Override

public void call() {

System.out.println("喵~喵");

}

}

 

 

然后我们只要通过以下方式就可以动态加载我们所用到的类了:

package com.xue.reflect;

 

public class CallTest {

 

public static void main(String[] args) {

CallTest ct = new CallTest();

ct.call("com.xue.reflect.Miao");//这边我们穿的类是Miao这个类名  所以Tiger这个类是不会加载的

 

}

 

 

 

public void call(String s) {

try {

Class c = Class.forName(s);//动态加载类  s为所用到的类的全称

try {

Animal animal = (Animal)c.newInstance(); //因为我们所有的类都是实现Animal接口  所以可以通过这种方式来实例化对象

animal.call(); //调用call类中重写的call方法

} catch (InstantiationException e) {

 

e.printStackTrace();

} catch (IllegalAccessException e) {

 

e.printStackTrace();

}

 

 

} catch (ClassNotFoundException e) {

 

e.printStackTrace();

}

 

}

 

}

 

 

 

接下来我们还可以通过某个类的类类型来获取该类的所有方法,成员变量,构造方法等  代码如下

package com.xue.reflect;

 

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

 

public class ReflectDetail {

 

public static void main(String[] args) {

ReflectDetail rd = new ReflectDetail();

rd.printMethods("hello"); //获取String类的所有方法及返回值和传参列表

rd.printField("hello"); //获取String类的所有成员变量

rd.printConst("hello"); //获取String类的所有构造函数

 

 

}

 

//获取类的所有方法及返回值和传参列表

public void printMethods(Object o) {

Class c1 = o.getClass(); //获得该类的类类型

System.out.println(c1.getName()); //打印该类的名称

Method m[] = c1.getDeclaredMethods(); //获得该类所有的方法

for (Method me : m) {

 

System.out.print("ReturnType:"+me.getReturnType().getName()+"  Method:"+me.getName()+"   params: "); 

Class types[] = me.getParameterTypes(); //获得某个方法的传参列表

for (Class c : types) {

System.out.print(c.getName()+ " ");

}

 

System.out.println();

 

 

}

 

 

}

 

       //获得该类的所有成员变量

public void printField(Object o) {

Class c1 = o.getClass();

Field fs[] = c1.getDeclaredFields();

for (Field f : fs) {

Class type = f.getType();

System.out.print("Type :" + type.getSimpleName() + " ParamName: " + f.getName());

System.out.println();

}

}

 

       //获得该类的所有构造函数以及传参列表

public void printConst(Object o) {

Class c1 = o.getClass();

Constructor cons[] = c1.getConstructors();

for (Constructor con : cons) {

System.out.print("Constructor: "+ con.getName()+" params: ");

Class cs [] = con.getParameterTypes();

for (Class c : cs) {

System.out.print(c.getName()+" ");

}

System.out.println();

}

 

 

}

 

}

 

 

 

接下来我们要研究下泛型的本质 : 泛型的本质就是只在编译的时候有用,如果绕开编译就失去了效果

下面我们看个代码就了解了

package com.xue.reflect;

 

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.util.ArrayList;

import java.util.List;

 

public class ReflectGenerics {

 

public static void main(String[] args) {

List list1 = new ArrayList(); //list1 不加泛型

List<String> list2 =  new ArrayList<String> ();  //list2 加上泛型String

Class c1 = list1.getClass(); //分别获得两个类类型  看是否相同  

Class c2 = list2.getClass();

System.out.println("c1 == c2 ? : "+ (c1 == c2)); //如果相同的话说明加泛型和不加泛型都是同一个类! 结果为true 所以是相同类型

try {

Method m = c2.getMethod("add", Object.class);//我们这里用加了泛型的list2来做实验看能不能把数字1插进去 如果插进去了的话说明泛型只有在编译期有效果,说明我们已经绕开了泛型的限制

try {

Object o = m.invoke(list2, 1);//通过invoke方法来实现list.add(xxx)方法

System.out.println(list2.size());//如果这里输入为1的话说明我们已经把数字1成功插入到list2中了 !其结果就是已经插入  所以我们可以证实泛型的限制只在编译时候有效

} catch (IllegalAccessException e) {

 

e.printStackTrace();

} catch (IllegalArgumentException e) {

 

e.printStackTrace();

} catch (InvocationTargetException e) {

 

e.printStackTrace();

}

} catch (NoSuchMethodException e) {

 

e.printStackTrace();

} catch (SecurityException e) {

 

e.printStackTrace();

}

}

 

}

 

上面代码的结果为:

c1 == c2 ? : true

1

 

 

因为是第一次写博客  排版和表达能力都有点乱。。。请多多包涵  !如果有错误请帮忙指出下!

 

1
3
分享到:
评论

相关推荐

    java 反射机制详解

    Java 反射机制是 Java 语言中的一个重要特性,它允许程序在运行时动态地获取类的信息(如类名、属性、方法等)并调用对象的方法,甚至修改对象的状态。这一机制极大地增强了 Java 程序的灵活性和可扩展性,尤其是在...

    java反射机制详解

    ### Java反射机制详解 #### 一、反射机制是什么 反射机制是Java编程语言的一个核心特性,它允许程序在运行时动态地获取类的信息,并且能够动态地创建对象和调用对象的方法。简单来说,反射机制使得Java程序可以...

    JAVA反射机制详解

    ### JAVA反射机制详解 #### 一、JAVA反射机制概述 反射是Java编程语言的一个核心特性,它允许程序在运行时获取类的信息,并且可以动态地创建对象和调用方法。这种能力使得Java程序具备了高度的灵活性和扩展性。...

    java反射机制详解与应用.pdf

    Java 反射机制详解与应用 Java 反射机制是一种非常强大的动态相关机制,允许 Java 程序在运行时加载、探知、使用编译期间完全未知的类别。这种机制允许程序在运行时透过 Reflection APIs 取得任何一个已知名称的...

    java反射机制详解及Method.invoke解释.pdf

    Java 反射机制详解及 Method.invoke 解释 Java 反射机制是 Java 语言中的一种功能,允许程序在运行时访问和修改类、对象、方法、变量等的信息。这种机制提供了许多强大的功能,例如在运行时判断对象所属的类、构造...

    Java反射机制详解

    Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、对象等的内部信息,甚至可以动态调用方法和访问字段。这为程序员提供了极高的灵活性,使得代码能够在不预先知道具体类型的情况...

    java反射机制详解与应用

    Java反射机制是Java语言的一项强大功能,它允许程序在运行时动态地获取类的信息并操作类的对象。这一特性使得Java具有高度的灵活性和强大的扩展性,尤其是在开发框架和库时,反射机制起到了至关重要的作用。本文将...

    Java 反射机制详解

    Java反射机制是Java语言中的一种强大的工具,它允许程序在运行时动态地获取类的信息并操作类的对象。以下是对Java反射机制的详细解析: 1. 获取对象建模类的类型: - `getclass()`方法:每个Java对象都有`getclass...

    JAVA反射机制详解视频

    (通过反射获取无参构造方法并使用) (通过反射获取带参构造方法并使用) (通过反射获取私有构造方法并使用) (通过反射获取成员变量并使用) (通过反射获取无参无返回值成员方法并使用) (通过反射获取带参带返回值成员...

    android系统java反射机制详解

    Java反射机制是Java编程语言中的一个强大工具,它允许程序在运行时检查和操作类、接口、对象等的内部信息。在Android系统中,Java反射机制同样被广泛应用,尤其是在动态加载类、处理不确定类型的对象、调用私有方法...

Global site tag (gtag.js) - Google Analytics