Java--反射的逐步理解
层层引入反射的作用
一.类类型的概念:所有类都是对象,是Class类的实例对象,这个对象我们成为该类的类类型
1.下面是一个小的test,以产生3种方式的类类型:
public class test {
/**
* @param args
*/
public static void main(String[] args) {
foo user = new foo();
//任何一个类都包含一个隐含的静态成员变量class
Class c1 = foo.class;
Class c2 = user.getClass();
Class c3 = null;
try {
c3 = Class.forName("test.foo");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//c1 c2,c3是foo类的类类型
}
class foo{ void print(){ System.out.println("haha"); } }
2.其实数据类型也有自己的类类型
Class class1 = int.class;//int的类类型
Class class2 = String.class;
Class class3 = double.class;
Class class4 = Double.class;
System.out.println(class1);
System.out.println(class2.getSimpleName());
System.out.println(class3);
System.out.println(class4);
3.类类型可以创建类的实例对象
try {
foo h =(foo)c1.newInstance();//类类型可以创建该类的实例对象
//需要有无参数的构造方法
h.print();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
二.动态加载类
1.我们有这样的疑惑,如果一个主函数中有好多个类,其中有一个类出现错误,其他类都没法用,所以我们就想我们要用那个类就让那个类运行,并且不想在重新编译主类,这时候动态加载类就派上了用场,不用动态类的时候会出现类似这样的问题:

当然这种情况只会出现在我们手动采用javac编译导致的,开发工具让我们看不到这些细节的东西。.
2.我们先引出动态加载类的概念,class.forName("")是动态加载类,而new class()是静态加载类,本质区别是,静态加载类的时候,编译时类必须存在,而动态加载类不一定存在。
public class sum {
public static void main(String[] args) {
try
{
//动态加载类
//args[0]表示的是在main方法里面传进来的第一个参数
Class c = Class.forName(args[0]);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
三.类对类的操作
1.通过Method类获取成员方法
/**
* 获取成员方法
* Method类,方法对象
* 一个成员方法就是一个Method对象
* getMethods()方法获取所有的public的函数,包括父类继承而来的
* getDeclaredMethods()获取的是所有该类自己声明的方法,不问访问权限
* @param obj
*/
public static void printClassMessage(Object obj) {
Class c1 = obj.getClass();
System.out.println(c1.getName());
Method[] ms = c1.getMethods();//c.getDeclaredMethods()
for (int i = 0; i < ms.length; i++) {
//得到方法的返回值类型的类类型
Class returnType = ms[i].getReturnType();
System.out.print(returnType.getName()+"");
//得到方法的名称
System.out.print(ms[i].getName()+"(");
//获取参数类型--->得到的是参数列表的类型的类类型
Class[] paramTypes = ms[i].getParameterTypes();
for (Class class1 : paramTypes) {
System.out.println(class1.getName());
}
System.out.println(")");
} }
2.通过Field类获取成员变量
/**
* 获取成员变量
* 成员变量也是对象
* java.lang.reflect.Field
* Filed类封装了关于成员变量的操作
* getFileds()方法获取的是所有的public的成员变量的信息
* getDeclaredFiled获取的是该类自己声明的成员变量的信息
* @param obj
*/ public static void printFieldMethod(Object obj) {
Class c1 = obj.getClass();
Field[] fs =c1.getDeclaredFields();
for (Field field : fs) {
//得到成员变量的类型的类类型
Class fieldType =field.getType();
String typeName = fieldType.getName();
//得到成员变量的名称
String fieldName=field.getName();
System.out.println(typeName+" "+fieldName);
}
}
3.通过Constructor类获取构造函数
/**
* 打印对象的构造函数的信息
* java.lang.Constructor中封装了构造函数的信息
* getConstructors获取所有的public的构造函数
* getDeclaredConstructors得到所有的构造函数
* @param obj
*/
public static void printConMessage(Object obj){
Class c = obj.getClass();
//Constructor cs = c.getConstructors();
Constructor[] cs =c.getDeclaredConstructors();
for (Constructor constructor : cs) {
System.out.println(constructor.getName()+"(");
Class[] paramTypes =constructor.getParameterTypes();
for (Class class1 : paramTypes) {
System.out.println(class1.getName()+",");
}
System.out.println(")");
}
}
四.反射
1.反射的作用是指定方法名称调用方法,demo如下:
public class demo {
public static void main(String[] args) {
//获取类的信息,就得先获取类的类类型
A a1 = new A();
Class c1 = a1.getClass();
/*
* 获取方法,名称和参数列表来决定
* getMethod获取的是public的方法
* getDelcaredMethod获取的的是自己声明的方法
*
*/
try {
Method method = c1.getMethod("print", int.class,int.class);
/*
* 方法的反射操作
* a1.print(10,20);方法的反射操作是用m对象来进行方法调用和a1.print调用的效果相同
* 方法如何没有返回值返回null,有返回值返回具体的返回值
* ...表示有几个参数传几个
*/
Object object =method.invoke(a1, 10,20);
Method method2 =c1.getMethod("print", new Class[]{String.class,String.class});
method2.invoke(a1, "hello","world");
Method method3 =c1.getMethod("print",null);
Object a = method3.invoke(a1);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class A{
public void print() {
System.out.println("hello world");
}
public void print(int a,int b){
System.out.println(a+b);
}
public void print(String a,String b){
System.out.println(a.toUpperCase()+b.toLowerCase());
}
}
2.案例,通过标准JavaBean的属性名获取其属性值
五.泛型
1.泛型是什么?看下面两个声明
//只能传String类型的数
ArrayList<String> list = new ArrayList<String>();
ArrayList list2 = new ArrayList();
2.泛型的本质,看下面的demo
public class fanxing {
/**
* 通过Class,Method来认识泛型的本质
* @param args
*/
public static void main(String[] args) {
//只能传String类型的数
ArrayList<String> list = new ArrayList<String>();
ArrayList list2 = new ArrayList();
list.add("hello");
//list.add(20);
Class c1 = list.getClass();
Class c2 =list2.getClass();
System.out.println(c1==c2);
}
}
由运行结果可以得出下面结论:
反射的操作都是编译之后的操作
c1==c2结果返回true说明编译之后的泛型是去泛型化的
Java中集合的泛型,是防止错误输入的,只是在编译阶段有效
3.利用方法的反射来操作,绕过编译
try {
Method a1 =c1.getMethod("add", Object.class);
Object a2 = a1.invoke(list, 2);
System.out.println(list.size());
System.out.println(list);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
代码的运行结果验证了泛型,得出结论,绕过编译操作就绕过了泛型
最后谢谢大家的阅读
Java--反射的逐步理解的更多相关文章
- JAVA反射机制及理解
JAVA反射 往往当我们面对一项新的知识时,我们往往需要知道三个方面,它是什么,它能做什么,它比原有知识强在哪里,我们该怎么使用它.当你能够解决这些问题时,便意味着你已经对这项知识入门了. 首先: 反 ...
- Java反射的浅显理解
一.回顾反射相关的知识 1.在xml文件中使用反射的好处: 1)代码更加灵活,后期维护只需要修改配置文件即可 · 初学者一般习惯于在代码本身上直接修改,后期也可以修改配置文件达到相同的目的 · 修改配 ...
- 我对java反射机制的理解
我们平常怎么用一个使用类,怎么使用类的方法?其实就是创建一个对象,并且通过这个对象调用这个方法.不过这有一个问题,就是这个对象的载体就和这个对象产生了耦合,怎么降低两者间的耦合呢?java的反射机制就 ...
- java反射机制的理解
反射机制是什么概念?大多都有介绍,指的是程序在运行状态中,能够加载一个只有类名的类,加载完之后会在堆上产生一个Class对象.通过这个 Class对象可以获得类的属性.方法和其他类信息.之前对反射的应 ...
- java反射的初理解
反射 获取类的方法: Class<?> aClass1 = Class.forName("TestDemo.refection.User");//通过类路径获取 Cla ...
- Java反射的一些理解
1.Class对象 VS. 实例对象 在Java中我们一般是这样使用类的:编写类,然后new对象,再调用方法.这里new出来的对象暂且称之为实例对象(instance).其实在这之前还涉及到一个Cla ...
- JAVA反射机制_获取字节码文件对象
是在运行状态中,对于任意一个类 (class文件),都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性: 这种动态获取的信息以及动态调用对象的方法的功能称为java语 ...
- Java反射机制获取Class文件
JAVA反射机制是在运行状态中,对于任意一个类(class文件),都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象方法的功能称为 ...
- java反射机制 + Method.invoke解释 getMethod + 反射理解
功能: 通过读取另一个Dll去创建一个控件(Form,Button,TextBox,DataGridView),然后对当中一些属性进行检查. 创建控件的大致流程是,Assembly->Modul ...
- (转)JAVA反射机制理解
JAVA反射机制: 通俗地说,反射机制就是可以把一个类,类的成员(函数,属性),当成一个对象来操作,希望读者能理解,也就是说,类,类的成员,我们在运行的时候还可以动态地去操作他们. 理论的东东太多也没 ...
随机推荐
- Java之【线程通信】--标志位练习2
定义一个线程A,输出1 - 10之间的整数,定义一个线程B,逆序输出1 - 10之间的整数,要求线程A和线程B交替输出 方法一:非标志位方法 package Homework; //1 定义一个线程A ...
- Java异常类(Throwable)
一.异常类体系 二.异常类由来与定义 [异常类的由来]:Java把程序在运行时出现的各种不正常情况也看成了对象, 提取属性和行为进行描述,比如异常名称,异常信息,异常发生位置,从而形成了各种异常类 [ ...
- Windows7 安装完成mysql dos启动服务出现服务名称无效
错误提示: WIN 7 cmd命令行下,net start mysql,出现 服务名无效提示: 错误分析: Mysql服务未安装 解决方案:在mysql 安装目录下bin文件夹 安装Shift+鼠 ...
- js中替换字符串(replace方法最简单的应用)
replace方法的语法是:stringObj.replace(rgExp, replaceText) 其中stringObj是字符串(string),reExp可以是正则表达式对象(RegExp)也 ...
- [0] (VDP)垂直开发模式
垂直管理 网格化管理 属地管理 横向管理 面向接口编程 面向对象编程(OOP) 设计模式(GOF.MVC.SOA) 依赖注入(DI/IoC) 面向方面编程(AOP) 领域驱动开发(DDD) 测试驱动开 ...
- linux 下用renameTo方法修改java web项目中文件夹名称问题
经测试,在Linux环境中安装tomcat,然后启动其中的项目,在项目中使用java.io.File.renameTo(File dest)方法可行. 之前在本地运行代码可以修改,然后传到Linux服 ...
- android设置横竖屏
android:screenOrientation="portrait"
- 简单轻量级的一套JS 类库(RapidDevelopmentFramework.JS)
1.最近好久没有更新自己的博客了,一直在考虑自己应该写一些什么.4.2日从苏州回到南京的路上感觉自己的内心些崩溃和失落,我就不多说了? 猛然之间我认为自己需要找一下内心的平衡.决定开发属于自己一套快速 ...
- 合并静态库出现 can't move temporary file错误
静态库的制作就不说了很简单,网上也很多例子,这里主要讲下我合并通用静态库时候遇见的坑,在合并前注意.a文件一定要正确,我有一次scheme选了release但是device忘了换,结果怼着两个模拟器静 ...
- 用Eclipse的snippets功能实现代码重用
snippets功能实现代码重用 Snippets 代码片段是Eclipse的一个插件. 很多时候可以通过这个功能,重复使用常用的代码片段,加快开发效率. 创建一个代码段的步骤: 在Eclipse的e ...