Java学习笔记之反射
2015-06-03 09:59
309 查看
反射学习笔记
一、类的加载
1.简介:
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化操作。
2.加载:
是指将xxx.class文件读入内存,并为之创建一个Class对象。
注意:任何类被加载时系统都会建立一个Class对象。
3.连接:
验证 是否有正确的内部结构,并和其他类协调一致
准备 负责为类的静态成员分配内存,并设置默认初始化值
解析 将类的二进制数据中的符号引用替换为直接引用
4.类加载器
负责将xxx.class文件加载到内存中,并为之生成对应的Class对象。
5.类加载器的作用
Bootstrap ClassLoader:根类加载器也称为引导类加载器,负责Java核心类的加载。例如System,String等。在JDK中JRE的lib目录下rt.jar文件中,如图1所示。C:\ProgramFiles\Java\jre1.8.0_45\lib
图1
Extension ClassLoader:扩展类加载器。负责JRE的扩展目录中jar包的加载。在JDK中JRE的lib目录下ext目录。如图2所示。
C:\ProgramFiles\Java\jre1.8.0_45\lib\ext
图2
System ClassLoader:系统类加载器。负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径。
二、反射
1.简介:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
2. 获取字节码文件对象的方式
方式1:通过Object类中getClass()方法,返回当前对象所对应的字节码文件对象
方式2:通过类名.class 完成返回一个字节码文件对象
方式3:(推荐使用)通过Class类中的forName()方法完成
public static Class<?> forName(StringclassName)
//className需要使用的是 完整的类名称包名.类名
测试代码:
//自定义类
public
class Person {
//构造方法
public Person() {
super();
}
}
//测试类
public
class ReflectDemo {
public
static void main(String[]
args) throws
ClassNotFoundException {
//方式1:
Person p = new Person();
Class c =
p.getClass();
System.out.println(c);//注意:字节码文件对象就是xxx.class文件
//方式2:
// Integer.class;
// int.class;
// String.class;
// char.class
//所有类型(基本类型和引用类型)都有字节码文件
Class c2 = Person.class;//类名.class返回Class对象。
System.out.println(c2);
//方式3:推荐使用第三种方法
Class c3 = Class.forName("cn.itcast_01_Reflect.Person");//包名.类名
System.out.println(c3);
}
}
输出结果:
class cn.itcast_01_Reflect.Person
class cn.itcast_01_Reflect.Person
classcn.itcast_01_Reflect.Person
说明:class 包名.类名
3.通过反射获取构造方法并创建对象
Class类简介:
Class类构造方法:无
常用方法:
public Constructor<?>[]getConstructors()//获取的是所有的public修饰的构造方法
public Constructor<T>getConstructor(Class<?>... parameterTypes)//获取的是指定的public修饰的构造方法
publicConstructor<?>[]getDeclaredConstructors()//获取所有的构造方法,包含私有。
publicConstructor<T>getDeclaredConstructor(Class<?>...parameterTypes)//获取指定的构造方法,包含私有。
Constructor类简介:提供关于类的单个构造方法的信息以及对它的访问权限。
注意:在反射中,把构造方法封装成一个类。
构造方法:无
常用方法:
public TnewInstance(Object...initargs) //创建对象
AccessibleObject类简介:
AccessibleObject 类是 Field、Method 和Constructor 对象的基类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力。从JDK1.2开始。
构造方法:
protected AccessibleObject() //构造方法:仅供 Java 虚拟机使用。
常用方法:
public void setAccessible(boolean flag)//取消java中 权限修饰符的检测
测试案例1:通过反射的方式,创建对象
//自定义类
public
class Person {
public Stringname;
public
int age;
private Stringaddress;
//构造方法
public Person() {
super();
}
//私有构造方法
private Person(Stringname) {
super();
this.name =name;
}
public Person(Stringname,
intage, String
address) {
super();
this.name =name;
this.age =age;
this.address =address;
}
//没有返回值没有参数的方法
public
void method1(){
System.out.println("没有返回值没有参数的方法");
}
//没有返回值,有参数的方法
public
void method2(String name){
System.out.println("没有返回值,有参数的方法 name:"
+ name);
}
//有返回值,没有参数的方法
public
int method3(){
System.out.println("有返回值,没有参数的方法");
return 12345;
}
//有返回值,有参数的方法
public Stringmethod4(Stringstr){
System.out.println("有返回值,有参数的方法 , str:" +str);
return"day27" +
str;
}
//私有方法
private
void method5(){
System.out.println("我是私有方法");
}
@Override
public StringtoString() {
return"Person [name=" +
name + ", age=" +
age + ",address="
+
address + "]";
}
}
//测试类
public
class ReflectDemo {
public
static void main(String[]
args) throws
ClassNotFoundException,NoSuchMethodException,
SecurityException,InstantiationException,
IllegalAccessException,IllegalArgumentException,
InvocationTargetException{
//通过反射的方式,创建对象
//1、获取Person类的字节码文件对象
Class c = Class.forName("cn.itcast_01_Reflect.Person");
//包名.类名
//2、获取构造方法
//2.1 获取空参构造方法:
Constructor con =
c.getConstructor(null);//获取空参构造方法
//3.1、通过空参数构造方法,创建对象
Object obj =
con.newInstance(null); //父类引用指向子类对象。
System.out.println(obj);
//2.2 获取有参构造方法
Constructor con1 =
c.getConstructor(String.class,int.class, String.class);
//3.2、通过有参数构造方法,创建对象
Object obj1 =
con1.newInstance("小明", 20 ,"北京");
System.out.println(obj1);
}
}
//输出结果
Person[name=null, age=0, address=null]
Person[name=小明,age=20, address=北京]
测试案例2:通过反射的方式,创建对象(获取私有构造函数,创建对象)
//自定义类和测试案例1相同,此处略。
//测试类
public
class ReflectDemo3 {
public
static void main(String[]
args) throws
ClassNotFoundException,NoSuchMethodException,
SecurityException, InstantiationException,
IllegalAccessException,IllegalArgumentException,
InvocationTargetException {
//1、获取Person类的字节码文件
Class c = Class.forName("cn.itcast_01_Reflect.Person");
//2、获取私有的构造方法
Constructor con = c.getDeclaredConstructor(String.class);
//System.out.println(con);//打印私有构造方法
//3、取消检查,暴力访问
con.setAccessible(true);
//4、创建对象
Object obj =
con.newInstance("小明");
System.out.println(obj);//打印对象
}
}
输出结果:
Person [name=小明, age=0, address=null]
4. 通过反射获取成员方法并使用
Class类中常用方法
public Method[] getMethods()//获取所有public修饰的普通方法,包含继承的public方法
public Method[] getDeclaredMethods()//获取所有的方法包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
public Method getMethod(String name,Class<?>... parameterTypes) //获取指定的public修饰的普通方法
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)//获取指定的普通方法包含私有。
Method类中常用方法:
public
Object invoke(Object obj,Object...
args)//执行获取到的方法
暴力访问
method.setAccessible(true);
注意:不建议使用暴力反射,因为他破坏类的封装特性。
5.通过反射获取成员变量并使用
获取所有成员
getFields,getDeclaredFields
获取单个成员
getField,getDeclaredField
修改成员的值
set(Object obj,Object value)
反射常见问题:
什么时候用反射?
当类不确定时,用反射技术
反射作用:
可以获取一个类中所有的属性和成员,不管是共有还是私有。
反射的好处?
大大的提高了程序的可扩展性
反射的缺点:
破坏类的封装特性。
三、动态代理
代理:本来应该自己做的事情,请了别人来做,被请的人就是代理对象
动态代理:在程序运行过程中产生的对象。而程序运行过程中产生对象其实就是反射,所以,动态代理其实就是通过反射来生成一个代理。
四、枚举
Java的枚举是从JDK1.5开始支持的,用的少,一般用类来代替,相当于一个特殊的java类和类的定义几乎一样。
1、枚举类可以有构造方法,但必须是private的,不能new出对象,可以用Enum.valueOf(Class c,String s)方法创建对象
2、枚举是否可以继承类?
不能,所有的枚举都继承自java.lang.Enum类。由于Java不支持多继承,所以枚举对象不能再继承其他类
3、在枚举种,可以使用抽象方法吗?
可以,需要实现抽象方法
4、枚举可以用增强for循环来遍历
5、枚举可以在switch语句中使用
6、枚举可以实现接口
7、可用枚举定义常量,和C语言类似。
五、泛型的擦除:
泛型的约束只在编译器有效,当编译通过后产生了一个.class的字节码文件。该字节码文件中没有泛型。
六、jdk5与jdk7的新特性
JDK5:
自动装箱和自动拆箱,泛型, 增强for循环,静态导入,可变参数,枚举
JDK7:
二进制字面量,数字字面量可以出现下划线,switch语句可以用字符串, 泛型简化, 异常的多个catch合并
一、类的加载
1.简介:
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化操作。
2.加载:
是指将xxx.class文件读入内存,并为之创建一个Class对象。
注意:任何类被加载时系统都会建立一个Class对象。
3.连接:
验证 是否有正确的内部结构,并和其他类协调一致
准备 负责为类的静态成员分配内存,并设置默认初始化值
解析 将类的二进制数据中的符号引用替换为直接引用
4.类加载器
负责将xxx.class文件加载到内存中,并为之生成对应的Class对象。
5.类加载器的作用
Bootstrap ClassLoader:根类加载器也称为引导类加载器,负责Java核心类的加载。例如System,String等。在JDK中JRE的lib目录下rt.jar文件中,如图1所示。C:\ProgramFiles\Java\jre1.8.0_45\lib
图1
Extension ClassLoader:扩展类加载器。负责JRE的扩展目录中jar包的加载。在JDK中JRE的lib目录下ext目录。如图2所示。
C:\ProgramFiles\Java\jre1.8.0_45\lib\ext
图2
System ClassLoader:系统类加载器。负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径。
二、反射
1.简介:
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
2. 获取字节码文件对象的方式
方式1:通过Object类中getClass()方法,返回当前对象所对应的字节码文件对象
方式2:通过类名.class 完成返回一个字节码文件对象
方式3:(推荐使用)通过Class类中的forName()方法完成
public static Class<?> forName(StringclassName)
//className需要使用的是 完整的类名称包名.类名
测试代码:
//自定义类
public
class Person {
//构造方法
public Person() {
super();
}
}
//测试类
public
class ReflectDemo {
public
static void main(String[]
args) throws
ClassNotFoundException {
//方式1:
Person p = new Person();
Class c =
p.getClass();
System.out.println(c);//注意:字节码文件对象就是xxx.class文件
//方式2:
// Integer.class;
// int.class;
// String.class;
// char.class
//所有类型(基本类型和引用类型)都有字节码文件
Class c2 = Person.class;//类名.class返回Class对象。
System.out.println(c2);
//方式3:推荐使用第三种方法
Class c3 = Class.forName("cn.itcast_01_Reflect.Person");//包名.类名
System.out.println(c3);
}
}
输出结果:
class cn.itcast_01_Reflect.Person
class cn.itcast_01_Reflect.Person
classcn.itcast_01_Reflect.Person
说明:class 包名.类名
3.通过反射获取构造方法并创建对象
Class类简介:
Class类的实例表示正在运行的Java 应用程序中的类和接口
Class类构造方法:无
常用方法:
public Constructor<?>[]getConstructors()//获取的是所有的public修饰的构造方法
public Constructor<T>getConstructor(Class<?>... parameterTypes)//获取的是指定的public修饰的构造方法
publicConstructor<?>[]getDeclaredConstructors()//获取所有的构造方法,包含私有。
publicConstructor<T>getDeclaredConstructor(Class<?>...parameterTypes)//获取指定的构造方法,包含私有。
Constructor类简介:提供关于类的单个构造方法的信息以及对它的访问权限。
注意:在反射中,把构造方法封装成一个类。
构造方法:无
常用方法:
public TnewInstance(Object...initargs) //创建对象
AccessibleObject类简介:
AccessibleObject 类是 Field、Method 和Constructor 对象的基类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力。从JDK1.2开始。
构造方法:
protected AccessibleObject() //构造方法:仅供 Java 虚拟机使用。
常用方法:
public void setAccessible(boolean flag)//取消java中 权限修饰符的检测
测试案例1:通过反射的方式,创建对象
//自定义类
public
class Person {
public Stringname;
public
int age;
private Stringaddress;
//构造方法
public Person() {
super();
}
//私有构造方法
private Person(Stringname) {
super();
this.name =name;
}
public Person(Stringname,
intage, String
address) {
super();
this.name =name;
this.age =age;
this.address =address;
}
//没有返回值没有参数的方法
public
void method1(){
System.out.println("没有返回值没有参数的方法");
}
//没有返回值,有参数的方法
public
void method2(String name){
System.out.println("没有返回值,有参数的方法 name:"
+ name);
}
//有返回值,没有参数的方法
public
int method3(){
System.out.println("有返回值,没有参数的方法");
return 12345;
}
//有返回值,有参数的方法
public Stringmethod4(Stringstr){
System.out.println("有返回值,有参数的方法 , str:" +str);
return"day27" +
str;
}
//私有方法
private
void method5(){
System.out.println("我是私有方法");
}
@Override
public StringtoString() {
return"Person [name=" +
name + ", age=" +
age + ",address="
+
address + "]";
}
}
//测试类
public
class ReflectDemo {
public
static void main(String[]
args) throws
ClassNotFoundException,NoSuchMethodException,
SecurityException,InstantiationException,
IllegalAccessException,IllegalArgumentException,
InvocationTargetException{
//通过反射的方式,创建对象
//1、获取Person类的字节码文件对象
Class c = Class.forName("cn.itcast_01_Reflect.Person");
//包名.类名
//2、获取构造方法
//2.1 获取空参构造方法:
Constructor con =
c.getConstructor(null);//获取空参构造方法
//3.1、通过空参数构造方法,创建对象
Object obj =
con.newInstance(null); //父类引用指向子类对象。
System.out.println(obj);
//2.2 获取有参构造方法
Constructor con1 =
c.getConstructor(String.class,int.class, String.class);
//3.2、通过有参数构造方法,创建对象
Object obj1 =
con1.newInstance("小明", 20 ,"北京");
System.out.println(obj1);
}
}
//输出结果
Person[name=null, age=0, address=null]
Person[name=小明,age=20, address=北京]
测试案例2:通过反射的方式,创建对象(获取私有构造函数,创建对象)
//自定义类和测试案例1相同,此处略。
//测试类
public
class ReflectDemo3 {
public
static void main(String[]
args) throws
ClassNotFoundException,NoSuchMethodException,
SecurityException, InstantiationException,
IllegalAccessException,IllegalArgumentException,
InvocationTargetException {
//1、获取Person类的字节码文件
Class c = Class.forName("cn.itcast_01_Reflect.Person");
//2、获取私有的构造方法
Constructor con = c.getDeclaredConstructor(String.class);
//System.out.println(con);//打印私有构造方法
//3、取消检查,暴力访问
con.setAccessible(true);
//4、创建对象
Object obj =
con.newInstance("小明");
System.out.println(obj);//打印对象
}
}
输出结果:
Person [name=小明, age=0, address=null]
4. 通过反射获取成员方法并使用
Class类中常用方法
public Method[] getMethods()//获取所有public修饰的普通方法,包含继承的public方法
public Method[] getDeclaredMethods()//获取所有的方法包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
public Method getMethod(String name,Class<?>... parameterTypes) //获取指定的public修饰的普通方法
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)//获取指定的普通方法包含私有。
Method类中常用方法:
public
Object invoke(Object obj,Object...
args)//执行获取到的方法
暴力访问
method.setAccessible(true);
注意:不建议使用暴力反射,因为他破坏类的封装特性。
5.通过反射获取成员变量并使用
获取所有成员
getFields,getDeclaredFields
获取单个成员
getField,getDeclaredField
修改成员的值
set(Object obj,Object value)
反射常见问题:
什么时候用反射?
当类不确定时,用反射技术
反射作用:
可以获取一个类中所有的属性和成员,不管是共有还是私有。
反射的好处?
大大的提高了程序的可扩展性
反射的缺点:
破坏类的封装特性。
三、动态代理
代理:本来应该自己做的事情,请了别人来做,被请的人就是代理对象
动态代理:在程序运行过程中产生的对象。而程序运行过程中产生对象其实就是反射,所以,动态代理其实就是通过反射来生成一个代理。
四、枚举
Java的枚举是从JDK1.5开始支持的,用的少,一般用类来代替,相当于一个特殊的java类和类的定义几乎一样。
1、枚举类可以有构造方法,但必须是private的,不能new出对象,可以用Enum.valueOf(Class c,String s)方法创建对象
2、枚举是否可以继承类?
不能,所有的枚举都继承自java.lang.Enum类。由于Java不支持多继承,所以枚举对象不能再继承其他类
3、在枚举种,可以使用抽象方法吗?
可以,需要实现抽象方法
4、枚举可以用增强for循环来遍历
5、枚举可以在switch语句中使用
6、枚举可以实现接口
7、可用枚举定义常量,和C语言类似。
五、泛型的擦除:
泛型的约束只在编译器有效,当编译通过后产生了一个.class的字节码文件。该字节码文件中没有泛型。
六、jdk5与jdk7的新特性
JDK5:
自动装箱和自动拆箱,泛型, 增强for循环,静态导入,可变参数,枚举
JDK7:
二进制字面量,数字字面量可以出现下划线,switch语句可以用字符串, 泛型简化, 异常的多个catch合并
相关文章推荐
- 关于Eclipse的Indigo和MyEclipse 2013版中文注释时字体太小的问题
- struts2中对象的获取
- [置顶]iOS_Spring自动生成Model,Service,Controller 之 使用教程
- [置顶]iOS_Spring自动生成Model,Service,Controller 之 介绍
- iOS_Spring preUrl参数
- iOS_Spring basePath参数
- Java TreeSet的使用 (LeetCode Contains Duplicate III )
- Java 入门课程视频实战-初级 上线了,猜拳游戏,ATM实战,欢迎围观
- 使用IntelliJ IDEA,gradle开发Java web应用步骤
- 关于Spring jar包下载地址以及方法
- 02、Spring_web.xml
- java中byte取值范围为什么是 -128到127
- 利用java mail发送邮件
- 利用java mail发送邮件
- webservice 的wsdl文件生成客户端java类
- java虚拟机的垃圾回收机制
- 用Ajax配合Restull实现SpringMVC的文件上传
- 有效处理Java异常三原则
- Google java编程技术规范
- Google java编程技术规范