j2se学习中的一些零碎知识点9之反射
2017-11-30 12:17
363 查看
1、反射的一些基础知识:
反射的基本概念:反射的概念是由Smith在1982年首次提出,主要是指程序可以访问、检测和修改它本身状态和行为的一种能力,并根据自身行为的状态和结果,调整或者修改应用所描述行为的状态和相关的语义。Java中,反射是一种强大的工具,是能够创建灵活的代码,这些代码可以在运行时装配,无需在组建之间进行源代码链接。反射允许我们在编写与执行时,是我们的程序代码能够接入装载到JVM中的内部信息,而不是源代码中选定的类协作的代码。这使反射成为构建灵活的主要工具。但是需要注意的是,如果使用不当,反射的成本很高。
反射机制的优点:1、反编译:.class --> .java;2、通过反射机制访问java对象的属性,方法,构造方法等。
反射的两个缺点:
a、性能问题。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。用于字段和方法接入时反射要远远慢于直接代码。性能问题的程度取决于程序中是如何使用反射的。如果它作为程序运行中相对很少涉及的部分,缓慢的性能将不会是一个问题。
b、使用反射会模糊程序内部实际要发生的事情。程序人员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术会带来维护问题。反射代码比相对应的直接代码更复杂。解决这些问题的最佳方案就是保守地使用反射--仅在于它可以真正增加灵活性的地方--记录其在目标类中的使用。
反射机制中主要需要掌握的类型:java.lang.Class;(可以认为代表.class文件) java.lang.reflect.Constructor; java.lang.reflect.Field; java.lang.reflect.Method; java.lang.reflect.Modifier;
获取Class类型对象的三种方式:
第一种方式:java.lang.Class类中的静态方法forName(String className)方法返回Class类型的对象,该对象代表的是整个类。(有时候必须使用类全名的字符串作为参数。)(forName静态方法是将某个.class文件装载到JVM中的过程,所以如果类中有静态语句块,静态语句块会执行。)
第二种方式:java中的每个类型都有class属性,如Class c = Employee.class;(不会执行Employee类中的静态语句块。)(需要注意,Class c = int.class; 即c代表int类型。)
第三种方式:java语言中任何一个java对象都有getClass方法,如Employee e = new Employee(); Class c = e.getClass();(java.lang.Object类中的getClass()方法,返回的是这个对象的运行时类。)
需要注意的是,在JVM中运行时类存在唯一,即 Class c1 = java.util.Date.class; Class c2 = Class.forName("java.util.Date"); System.out.println(c1 = c2); ,结果为true。
2、通过java.lang.Class类中的newInstance()方法创建由该类对象表示的类的新实例:(底层调用指定类中的无参数构造方法)(Class类可以使用泛型)
3、关于java中的可变长参数:(需要注意,可变长参数可以等同看作数组)
可变长参数可以使用length属性:(也可以使用下标,如args[i])
需要注意的是,可变长参数只能放在参数列表的最后,以下代码编译不能通过:
4、IO和Properties类的联合应用:
从字节输入流中加载适当的list(键值对形式):
在指定目录下创建dbinfo.properties文件,文件内容如下:(属性文件中的格式固定,“=”号可以替换成“:”或者是空格。java中规范要求属性文件以“.properties”。如果“空格”,“等号”,“冒号”都有,按最前的作为分隔符。)
示例代码:
需要在创建的java项目中添加一个dbinfo文件:
5、java.lang.Class(类)、java.lang.reflect.Field(类中的属性)和java.lang.reflect.Modifier类(类中的修饰符)
java.lang.Class类中的getFields()方法:用于获取Class类对象表示的public修饰符修饰的Field对象数组
java.lang.Class类中的getDeclaredFields()方法:用于获取Class类对象表示的所有Field对象数组:
java.lang.Class类中的getDeclaredField方法:用于获取Class类对象表示的Field对象(通过传递属性名字符串参数)
java.lang.reflect.Field类中的getType()方法:用于获取Field类对象表示的用于标识声明域的类型的Class对象
java.lang.Class类中的getName()方法:用于获取Class类对象表示的实体的名字,作为字符串返回(包括类、接口、数组类、基本数据类型或者是void)
java.lang.Class类中的getSimpleName()方法:用于获取Class类对象表示的在源码中给定的底层类简写的名字
java.lang.Class类中的getModifiers()方法:用于获取类或者接口中的java语言中的修饰符(编码成int类型)
java.lang.reflect.Field类中的getModifiers()方法:用于获取Field对象表示的域的java语言修饰符(作为int类型数据返回)
java.lang.reflect.Modifier类中的toString(int mod)方法:返回指定的修饰符标识的字符串名(通过传入iint类型的参数)
java.lang.reflect.Field类中的set(Object object, Object value)方法:通过Field类对象相关的field域设置指定的值(指定的值为第二个参数Object value)(第一个参数传递的是包含该属性的类对象)
java.lang.reflect.Field类中的get(Object obj)方法:(通过在指定的类对象上,返回这个Field对象的域的值)
java.lang.reflect.AccessibleObject类中的setAccessible(boolean flag)方法:打破封装,将这个对象的可访问标志设置为指定的布尔值(java.lang.reflect.Field继承自java.lang.reflect.AccessibleObject)
6、java.lang.reflect.Method:类中的方法
java.lang.Class类中的getDeclaredMethods()方法:用于获取Class类对象表示的所有方法对象数组,该数组反射对象类或者接口声明中的所有方法
java.lang.reflect.Method类中的getReturnType()(获取返回值的Class类型)、getModifers()(获取修饰符表示的int类型的值)、getName()(获取方法的字符串名字)、getParameterTypes()方法(获取形式参数列表表示的Class类型数组):(以下方法和java.lang.reflect.Field类中的方法类似,不赘述)
7、获取某个特定的方法,通过反射机制执行:
java.lang.Class类中的getDeclaredMethod(String name, Class ... parameterType)方法:用于获取Class类对象相关的Method类对象(通过传递字符串方法名和可变长Class类型的形参列表两个参数)
java.lang.reflect.Method类中的invoke(Object obj, Object ... args)方法:在传递的指定的对象(第一个参数)调用对象类上的方法,实参列表为传递的指定可变长参数
8、java.lang.reflect.Constructor:类的构造方法
java.lang.Class类中的getDeclaredConstructor(Class ... parameterTypes)方法:用于获取Class类对象表示的构造器对象,这个构造器对象反射指定类或者接口的构造器
java.lang.Class类中的getDeclaredConstructors()方法:用于获取Class类对象表示的构造器对象数组,这个构造器对象数组反射在类中声明的所有构造器
java.lang.reflect.Constructor类中的getModifiers()方法:用于返回Constructor类对象表示构造器的java语言修饰符(作为int类型数据返回)
java.lang.reflect.Constructor类中的getParameterTypes():用于获取Constructor类对象表示的Class类对象数组,这个类对象数组用于表示在构造器中按照一定次序形式参数类型
java.lang.reflect.Constructor类中的getGenericExceptionTypes()方法:用于返回Constructor类对象的Type类对象数组,这个数组表示声明抛出的异常
9、获取某个特定的构造方法,然后创建对象:
java.lang.reflect.Constructor类中的newInstance(Object ... initargs)方法:使用Constructor类对象表示的构造器,创建和初始化构造器声明的类的实例(使用指定的参数列表)
示例代码:
10、关于类获取父类和父接口:
java.lang.Class类中的getSuperclass()方法:用于获取Class类对象表示的实体(类、接口、基本数据类型或者是void)的Class父类对象
java.lang.Class类中的getInterfaces()方法:通过Class类对象表示的这个类或者接口确定它实现的接口,并返回这个Class类对象
反射的基本概念:反射的概念是由Smith在1982年首次提出,主要是指程序可以访问、检测和修改它本身状态和行为的一种能力,并根据自身行为的状态和结果,调整或者修改应用所描述行为的状态和相关的语义。Java中,反射是一种强大的工具,是能够创建灵活的代码,这些代码可以在运行时装配,无需在组建之间进行源代码链接。反射允许我们在编写与执行时,是我们的程序代码能够接入装载到JVM中的内部信息,而不是源代码中选定的类协作的代码。这使反射成为构建灵活的主要工具。但是需要注意的是,如果使用不当,反射的成本很高。
反射机制的优点:1、反编译:.class --> .java;2、通过反射机制访问java对象的属性,方法,构造方法等。
反射的两个缺点:
a、性能问题。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。用于字段和方法接入时反射要远远慢于直接代码。性能问题的程度取决于程序中是如何使用反射的。如果它作为程序运行中相对很少涉及的部分,缓慢的性能将不会是一个问题。
b、使用反射会模糊程序内部实际要发生的事情。程序人员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术会带来维护问题。反射代码比相对应的直接代码更复杂。解决这些问题的最佳方案就是保守地使用反射--仅在于它可以真正增加灵活性的地方--记录其在目标类中的使用。
反射机制中主要需要掌握的类型:java.lang.Class;(可以认为代表.class文件) java.lang.reflect.Constructor; java.lang.reflect.Field; java.lang.reflect.Method; java.lang.reflect.Modifier;
获取Class类型对象的三种方式:
第一种方式:java.lang.Class类中的静态方法forName(String className)方法返回Class类型的对象,该对象代表的是整个类。(有时候必须使用类全名的字符串作为参数。)(forName静态方法是将某个.class文件装载到JVM中的过程,所以如果类中有静态语句块,静态语句块会执行。)
第二种方式:java中的每个类型都有class属性,如Class c = Employee.class;(不会执行Employee类中的静态语句块。)(需要注意,Class c = int.class; 即c代表int类型。)
第三种方式:java语言中任何一个java对象都有getClass方法,如Employee e = new Employee(); Class c = e.getClass();(java.lang.Object类中的getClass()方法,返回的是这个对象的运行时类。)
需要注意的是,在JVM中运行时类存在唯一,即 Class c1 = java.util.Date.class; Class c2 = Class.forName("java.util.Date"); System.out.println(c1 = c2); ,结果为true。
2、通过java.lang.Class类中的newInstance()方法创建由该类对象表示的类的新实例:(底层调用指定类中的无参数构造方法)(Class类可以使用泛型)
3、关于java中的可变长参数:(需要注意,可变长参数可以等同看作数组)
package com.geeklicreed.j2se; /* * 关于java中的可变长参数 */ public class Test { //m1方法有一个int类型的可变长参数 public static void m1(int... a){ //m1方法在调用的时候,传递的实参可以是0-n个 System.out.println("Test"); } //如果有可以精确匹配的方法,则调用该方法,不会再去执行可变长参数的那个方法 public static void m1(int i){ System.out.println(i); } public static void main(String []args){ m1(); m1(1); m1(1, 2); m1(3, 4, 5, 6, 7); /* `输出结果为: Test 1 Test Test */ } }
可变长参数可以使用length属性:(也可以使用下标,如args[i])
//可变长参数可以等同看作数组 public static void m2(Sring... args){ for(int i = 0; i < args.length; i++){ System.out.println(args[i]); } }
需要注意的是,可变长参数只能放在参数列表的最后,以下代码编译不能通过:
public static void m4(String... a, int i){}
4、IO和Properties类的联合应用:
从字节输入流中加载适当的list(键值对形式):
在指定目录下创建dbinfo.properties文件,文件内容如下:(属性文件中的格式固定,“=”号可以替换成“:”或者是空格。java中规范要求属性文件以“.properties”。如果“空格”,“等号”,“冒号”都有,按最前的作为分隔符。)
示例代码:
需要在创建的java项目中添加一个dbinfo文件:
package com.geeklicreed.j2se; import java.io.FileInputStream; import java.util.Properties; /* * 关于java中的可变长参数 */ public class Test { public static void main(String []args) throws Exception{ //1、创建属性对象 Properties p = new Properties(); //和Map一样,只不过key和value只能存储字符串类型 //key不能重复,如果key重复则value覆盖 //2、创建输入流 FileInputStream fis = new FileInputStream("dbinfo"); //3、将fis流中的所有数据加载到属性对象中 p.load(fis); //所以现在属性对象中有(key=username,value=scott) //4、关闭流 fis.close(); //通过key获取value String v1 = p.getProperty("driver"); String v2 = p.getProperty("url"); String v3 = p.getProperty("username"); String v4 = p.getProperty("password"); System.out.println(v1); System.out.println(v2); System.out.println(v3); System.out.println(v4); /* 输出结果为: oracle.jdbc.driver.OracleDriver jdbc:oracle:thin:@192.168.1.100:1521:geeklicreed scott tiger */ } }
5、java.lang.Class(类)、java.lang.reflect.Field(类中的属性)和java.lang.reflect.Modifier类(类中的修饰符)
java.lang.Class类中的getFields()方法:用于获取Class类对象表示的public修饰符修饰的Field对象数组
java.lang.Class类中的getDeclaredFields()方法:用于获取Class类对象表示的所有Field对象数组:
java.lang.Class类中的getDeclaredField方法:用于获取Class类对象表示的Field对象(通过传递属性名字符串参数)
java.lang.reflect.Field类中的getType()方法:用于获取Field类对象表示的用于标识声明域的类型的Class对象
java.lang.Class类中的getName()方法:用于获取Class类对象表示的实体的名字,作为字符串返回(包括类、接口、数组类、基本数据类型或者是void)
java.lang.Class类中的getSimpleName()方法:用于获取Class类对象表示的在源码中给定的底层类简写的名字
java.lang.Class类中的getModifiers()方法:用于获取类或者接口中的java语言中的修饰符(编码成int类型)
java.lang.reflect.Field类中的getModifiers()方法:用于获取Field对象表示的域的java语言修饰符(作为int类型数据返回)
java.lang.reflect.Modifier类中的toString(int mod)方法:返回指定的修饰符标识的字符串名(通过传入iint类型的参数)
java.lang.reflect.Field类中的set(Object object, Object value)方法:通过Field类对象相关的field域设置指定的值(指定的值为第二个参数Object value)(第一个参数传递的是包含该属性的类对象)
java.lang.reflect.Field类中的get(Object obj)方法:(通过在指定的类对象上,返回这个Field对象的域的值)
java.lang.reflect.AccessibleObject类中的setAccessible(boolean flag)方法:打破封装,将这个对象的可访问标志设置为指定的布尔值(java.lang.reflect.Field继承自java.lang.reflect.AccessibleObject)
6、java.lang.reflect.Method:类中的方法
java.lang.Class类中的getDeclaredMethods()方法:用于获取Class类对象表示的所有方法对象数组,该数组反射对象类或者接口声明中的所有方法
java.lang.reflect.Method类中的getReturnType()(获取返回值的Class类型)、getModifers()(获取修饰符表示的int类型的值)、getName()(获取方法的字符串名字)、getParameterTypes()方法(获取形式参数列表表示的Class类型数组):(以下方法和java.lang.reflect.Field类中的方法类似,不赘述)
7、获取某个特定的方法,通过反射机制执行:
java.lang.Class类中的getDeclaredMethod(String name, Class ... parameterType)方法:用于获取Class类对象相关的Method类对象(通过传递字符串方法名和可变长Class类型的形参列表两个参数)
java.lang.reflect.Method类中的invoke(Object obj, Object ... args)方法:在传递的指定的对象(第一个参数)调用对象类上的方法,实参列表为传递的指定可变长参数
8、java.lang.reflect.Constructor:类的构造方法
java.lang.Class类中的getDeclaredConstructor(Class ... parameterTypes)方法:用于获取Class类对象表示的构造器对象,这个构造器对象反射指定类或者接口的构造器
java.lang.Class类中的getDeclaredConstructors()方法:用于获取Class类对象表示的构造器对象数组,这个构造器对象数组反射在类中声明的所有构造器
java.lang.reflect.Constructor类中的getModifiers()方法:用于返回Constructor类对象表示构造器的java语言修饰符(作为int类型数据返回)
java.lang.reflect.Constructor类中的getParameterTypes():用于获取Constructor类对象表示的Class类对象数组,这个类对象数组用于表示在构造器中按照一定次序形式参数类型
java.lang.reflect.Constructor类中的getGenericExceptionTypes()方法:用于返回Constructor类对象的Type类对象数组,这个数组表示声明抛出的异常
9、获取某个特定的构造方法,然后创建对象:
java.lang.reflect.Constructor类中的newInstance(Object ... initargs)方法:使用Constructor类对象表示的构造器,创建和初始化构造器声明的类的实例(使用指定的参数列表)
示例代码:
package com.geeklicreed.j2se; import java.lang.reflect.Constructor; public class ReflectTest { public static void main(String[] args) throws Exception { // 1、获取类 Class c = Class.forName("Customer"); // 2、获取特定的构造方法 Constructor con = c.getDeclaredConstructor(String.class, int.class); // 3、创建对象 Object o = con.newInstance("张三", 25); System.out.println(o); } } class Customer { String name; int age; @Override public String toString() { return "Customer [name=" + name + ", age=" + age + "]"; } public Customer(String name, int age) { super(); this.name = name; this.age = age; } }
10、关于类获取父类和父接口:
java.lang.Class类中的getSuperclass()方法:用于获取Class类对象表示的实体(类、接口、基本数据类型或者是void)的Class父类对象
java.lang.Class类中的getInterfaces()方法:通过Class类对象表示的这个类或者接口确定它实现的接口,并返回这个Class类对象
相关文章推荐
- j2se学习中的一些零碎知识点6之DecimalFormat数字类以及java中的集合
- j2se学习中的一些零碎知识点8之多线程
- j2se学习中的一些零碎知识点1之基础知识
- j2se学习中的一些零碎知识点7之流
- j2se学习中的一些零碎知识点2之基础知识
- j2se学习中的一些零碎知识点5之StringBuffer类,八种基本数据类型对应的包装类型和自动装
- j2se学习中的一些零碎知识点3之内部类和UML类图关系,以及软件包机制
- j2se学习中的一些零碎知识点4之字符串,数组和异常(使用数组实现冒泡排序算法和选择排序以及二分法查
- Web程序编程与AJAX学习中的一些零碎的知识点(一)
- 记录一些学习到的零碎的知识点。
- c++学习总结(一些零碎的小知识点)
- Struts2.0学习笔记 --- 一些零碎知识点
- Cocos2dx 学习记录 [2] 关于混合和高亮一些知识点的体会
- 记录整理入门的JavaScript学习一些重要知识点
- MySql学习笔记----一些小知识点
- 学习反射后的一些心得
- 一些知识点的初步理解_1(集成学习,ing...)
- 数据结构学习笔记10--栈和队列中的一些重点易错知识点
- 一些零碎的知识点
- 【学习日记】java反射的知识点总结