若你困于无风之地,我将为你奏响高空之歌
文章目录
- 一、int 和 Integer 对象
- 1. int 和 Integer 对象的区别
- 2. 变量比较问题:
- 二、反射
- 1. 反射机制定义
- 2. 反射的使用步骤
- 3. 一个小栗子
- 4. 反射的应用
一、int 和 Integer 对象
1. int 和 Integer 对象的区别
- Integer是int的包装类,int是基本数据类型;
- Integer变量必须实例化后才能使用;int变量不需要;
- Integer实际是对象的引用,指向此new的Integer对象,int是直接存储数据值 ;
- Integer的默认值是null;int的默认值是0。
2. 变量比较问题:
- 两个 new 出的 Integer 变量永远不相等,因为其存放的是对一个 Integer 变量的引用(内存地址不同)
Integer num1 = new Integer(1000);Integer num2 = new Integer(1000);System.out.println("num1 == num2 " + (num1 == num2) );
- Integer 变量与 int 变量进行比较时,若两个变量值相等,则返回true (包装类自动拆包为int,然后进行比较)
Integer num3 = new Integer(520);int num4 = 520;System.out.println("num3 == num4 " + (num3 == num4) );
- 非 new 生成的 Integer 变量和 new 生成的变量比较,结果为 false。(非 new 生成的 Integer 对象指向 java 常量池中的对象,new 生成的变量指向堆中新建的对象,两者在内存中的地址不同)
Integer num5 = new Integer(1314);Integer num6 = 1314;System.out.println("num5 == num6 " + (num5 == num6));
- 两个非 new 生成的 Integer 变量,若变量值在 -128~127 之间,则比较结果为 true,否则比较结果为 false (值在 -128 ~127 之间时,Java 会进行自动装箱,然后对值进行缓存,下次再有相同的值,会之间在缓存中取出使用。)
Integer num7 = -127;Integer num8 = -127;System.out.println("num7 == num8 " + (num7 == num8));Integer num9 = 128;Integer num10 = 128;System.out.println("num9 == num10 " + (num9 == num10));
自动装箱源码:
缓存是通过Integer的内部类IntegerCache来完成的,当值超出 -128 ~ 127 这个范围,会在堆中new出一个对象来存储。
public static Integer valueOf(String s, int radix) throws NumberFormatException {return Integer.valueOf(parseInt(s,radix));}/*** (1)在-128~127之内:静态常量池中cache数组是static final类型,cache数组对象会被存储于静态常量池中。* cache数组里面的元素却不是static final类型,而是cache[k] = new Integer(j++),* 那么这些元素是存储于堆中,只是cache数组对象存储的是指向了堆中的Integer对象(引用地址)* * (2)在-128~127 之外:新建一个 Integer对象,并返回。*/
public static Integer valueOf(int i) {assert IntegerCache.high >= 127;if (i >= IntegerCache.low && i <= IntegerCache.high) {return IntegerCache.cache[i + (-IntegerCache.low)];}return new Integer(i);}
二、反射
1. 反射机制定义
反射是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制。
通过反射机制,可以在运行时动态地获取类的实例,提高灵活性。但是反射需要解析字节码,使用反射会降低性能。
提高反射效率的方法:
- 通过setAccessible(true)关闭JDK的安全检查来提升反射速度;
- 多次创建一个类的实例时,有缓存会快很多;
- ReflflectASM工具类,通过字节码生成的方式加快反射速度。
2. 反射的使用步骤
- 获取类的 Class 对象实例
- 根据 Class 对象实例获取 Constructor 对象
- 使用 Constructor 对象的 newInstance 方法获取反射类对象
- 获取方法的 Method 对象
- 利用 invoke 方法调用方法
反射 API:
Class 类: 反射的核心类,可以获取类的属性,方法等信息。
Field 类: Java.lang.reflec 包中的类,表示类的成员变量,可以用来获取和设置类之中的属性值。
Method 类: Java.lang.reflec 包中的类,表示类的方法,它可以用来获取类中的方法信息或者执行方法。
Constructor 类: Java.lang.reflec 包中的类,表示类的构造方法。
3. 一个小栗子
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class Reflect {private int num;public Reflect(int num) {this.num = num;}public Reflect() {}public int getNum() {return num;}public void setNum(int num) {this.num = num;}public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Class clz = Class.forName("Reflect");Method setNumMethod = clz.getMethod("setNum",int.class );Constructor reflectConstructor = clz.getConstructor();Object reflectObj = reflectConstructor.newInstance();setNumMethod.invoke(reflectObj, 520);Method getReflectNum = clz.getMethod("getNum");System.out.println("Num = " + getReflectNum.invoke(reflectObj));}
}
4. 反射的应用
- JDBC 的数据库的连接
- Spring框架中的 xml 的配置模式
Spring 通过 XML 配置模式装载 Bean 的过程:
- 将程序内所有 XML 或 Properties 配置文件加载入内存中;
- Java类里面解析xml或properties里面的内容,得到对应实体类的字节码字符串以及相关的属性信息;
- 使用反射机制,根据这个字符串获得某个类的Class实例;
- 动态配置实例的属性。