java入门的注意点_Java基础之Integer使用的注意事项及面试题
JAVA中Integer对象的引用
JAVA中没有指针一说,但也有引用的概念。这里要说的主要是Integer是不是同一个对象。
1、先看一段代码:
public static void main(String[] args){
Integer a1 = 100;
Integer b1 = a1;//另一种也可以b1=100
Field field = null;
try {
field = a1.getClass().getDeclaredField("value");
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
field.setAccessible(true);
try {
field.set(a1, 5000);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("b1="+b1);
Integer c1 = 100;
System.out.println("c1="+c1);
}
结果:
b1=5000
c1=5000
从上面,首先这里要说明几个,
1)、对于Integer来说,-128-127之间的整型已经初始化放在IntegerCache中,如果是装箱的话,就会从这里面取对象。
2)、b1=a1到底是数字赋值还是同一个对象?这个从结果实际就可以看出来,b1和a1指向同一个对象,而不是同一个数值
3)、c1=100,说明对于-128-127之间的数值,都是从IntegerCache中获取的对象,100对应的Integer对象被改变后,后续对于100的装箱都被改变。因为获取cache中对象时用的是数组索引,而不是数值比较获取的。
不过修改这个缓存会比较危险,不介意。谁知道什么jar包或者什么平台来个100的装箱,但得到结果又不是100,到时就崩溃了。
2、通过上面描述,那么如果改成这样又是什么答案
public static void main(String[] args){
Integer a1 = 200;
Integer b1 = a1;
Field field = null;
try {
field = a1.getClass().getDeclaredField("value");
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
field.setAccessible(true);
try {
field.set(a1, 5000);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("b1="+b1);
Integer c1 = 200;
System.out.println("c1="+c1);
}
3、那么再改一下
public static void main(String[] args){
Integer a1 = new Integer(100);
Integer b1 = a1;
Field field = null;
try {
field = a1.getClass().getDeclaredField("value");
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
field.setAccessible(true);
try {
field.set(a1, 5000);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("b1="+b1);
Integer c1 = 100;
System.out.println("c1="+c1);
}
这又是什么答案。对于new的操作,是不进行装箱的,而是在堆中生成对象的。
理解了装箱、缓存、引用就不难理解了。可以自己试试。
先来点基础的知识
基本类型和包装类的对应
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
上述的八中基本数据类型的对应关系只有 int->Integer char->Character 两个变化较大,其余都只是将首字母转换为小写。
再来了解一下JDK5的新特性:自动装箱和拆箱
自动装箱:把基本类型转换为包装类类型
自动拆箱:把包装类类型转换为基本类型
public class Demo_Integer {
public static void main(String[] args) {
//JDK1.5之前
int a = 100;
Integer a1 = new Integer(a); //将基本数据类型包装成对象,装箱
int b = a1.intValue(); //将对象转换为基本数据类型,拆箱
//JDK1.5之后
int x = 100;
Integer x1 = x; //自动装箱,把基本数据类型转换为对象
int y = x1 + x; //自动拆箱,把对象转换为基本数据类型
}
}
注意事项
public class Demo_Integer {
public static void main(String[] args) {
Integer a = null;
int b = a + 100; //自动拆箱底层将会调用a.intValue(),a为null,自然会抛出 NullPointerException
System.out.println(b);
}
}
面试题
public class Demo_Integer {
public static void main(String[] args) {
Integer i1 = new Integer(97);
Integer i2 = new Integer(97);
System.out.println(i1 == i2);
System.out.println(i1.equals(i2));
System.out.println("-----------");
Integer i3 = new Integer(197);
Integer i4 = new Integer(197);
System.out.println(i3 == i4);
System.out.println(i3.equals(i4));
System.out.println("-----------");
}
}
Output:
false
true
-----------
false
true
-----------
原因:
new 是在堆内存开辟空间的,自然比较地址值(==)都为false.
由于Integer重写了equals方法,所以equals输出都为true.
你可能感觉太简单了,没有任何技术含量,因为上面的不是重点,看下面代码
public class Demo_Integer {
public static void main(String[] args) {
Integer i1 = 127;
Integer i2 = 127;
System.out.println(i1 == i2);
System.out.println(i1.equals(i2));
System.out.println("-----------");
Integer i3 = 128;
Integer i4 = 128;
System.out.println(i3 == i4);
System.out.println(i3.equals(i4));
System.out.println("-----------");
}
}
Output:
true
true
-----------
false
true
-----------
原因:
为什么当int大于127就是两个对象,127这个数字是不是觉得很熟悉?
-128到127是byte的取值范围,如果在这个取值范围内,自动装箱就不会创建新对象了,而从常量池中获取
超过了byte的取值范围就会在创建新对象
自动装箱其底层会调用valueOf()方法,简单源码分析(JDK1.8):
public final class Integer extends Number implements Comparable {
public static Integer valueOf(int i) {
//当 i >= -128 且 i <= 127 时,会直接将取缓冲区中的对象
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);//超过了byte取值范围会在堆内存创建
}
//内部类充当缓冲区
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
}
8种基本类型的包装类和对象池
java中基本类型的包装类的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型的包装类则没有实现。另外Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值小于等于127时才可使用对象池,也即对象不负责创建和管理大于127的这些类的对象
扩展知识
在jvm规范中,每个类型都有自己的常量池。常量池是某类型所用常量的一个有序集合,包括直接常量(基本类型,String)和对其他类型、字段、方法的符号引用。之所以是符号引用而不是像c语言那样,编译时直接指定其他类型,是因为java是动态绑定的,只有在运行时根据某些规则才能确定具体依赖的类型实例,这正是java实现多态的基础。
在JVM中,类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载7个阶段。而解析阶段即是虚拟机将常量池内的符号引用替换为直接引用的过程。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。
java入门的注意点_Java基础之Integer使用的注意事项及面试题相关推荐
- Java 入门课程视频实战-0基础 上线了,猜拳游戏,ATM实战,欢迎围观
Java 入门课程视频实战-0基础 已经上传完了.欢迎小伙伴们过来围观 直接进入: http://edu.csdn.net/course/detail/196 课程文件夹例如以下: 1 初识Java ...
- java入门123 pdf下载_Java入门123:一个老鸟的Java学习心得 pdf_IT教程网
资源名称:Java入门123:一个老鸟的Java学习心得 pdf 第1篇 Java语言基本语法 第1章 让自己的第一个Java程序跑起来 第2章 搭建自己的集成开发环境 第3章 Java中的基本数据类 ...
- java反射三种方法_Java基础入门要学哪些 怎么掌握反射和枚举
Java基础入门要学哪些?怎么掌握反射和枚举?Java是老牌编程语言,是一种可以撰写跨平台应用软件的面向对象的程序设计语言.Java所包含的基础知识点很多,只有掌握了这些知识才能更好地运用,下面就来给 ...
- java入门从哪下手_java新手0基础如何最快速的入门
一口不吃了一个胖子,心急吃不了热豆腐.当你点开这篇文这句话送给你. 零基础学Java只需办法适合,仍然有机遇进修好Java编程.初学Java就像交同伙从生疏到认识再到铁杆错误平生相伴,跟着进修的深刻, ...
- java构造一个水果类_Java基础入门之Object类、匿名内部类、构造方法的继承解析...
前言 大家好,我是Java进阶者.这篇文章我们主要介绍Java基础中的Object类.匿名内部类.构造方法的继承知识,一起来学习下吧! 一.Object类 1.Object类是所有类的父类,所有类都继 ...
- java 入门 博客园_java入门基础
什么是java? java是一门编程语言 编程语言有很多种 你比如 C语言 等等 为什么学习java呢! 因为你要和计算机交互 当然了你用汉语跟她说她听不懂 所以你要学习编程语言 那么额咱们的ja ...
- java基础入门txt下载地址_java基础入门-ZipOutputStream打包下载
今天跟大家聊聊使用ZipOutputStream打包下载,我下面是使用ant的jar打包的,因为他对应中文的支持比较好 大家也可以使用java.util.zip包里面的工具类打包,但是他对于中文不友好 ...
- java增强型for报错_Java基础——增强for循环
java1.5版本引入了一个增强for循环,基本原理和for循环类似. 语法声明:for(表达式:条件表达式) 举例:for (String str : set) 解释:set代表set集合,str代 ...
- java 继承与多态 习题_JAVA基础 第4章继承与多态_练习题_200910
Java基础第4章练习题大外软件学院 第4章继承与多态 一.选择题 1. 编译和运行以下两文件结果是( D ). //文件P1.java package MyPackage; class P1{ vo ...
最新文章
- Atitit.java jna 调用c c++ dll的原理与实践 总结 v2 q27
- 2014“云”盘点:改变着的互联网和被改变的云计算
- Python matplotlib 绘制散点图 还不收藏起来
- 关于Android制作.9.png图片
- DPDK 应用层对网卡进行配置(二十四)
- 【LeetCode从零单排】No19.RemoveNthNodeFromEndofList
- 阿里的财报,释放了什么信号?
- pthread_create如何传递两个参数以上的参数
- matlab Tips
- 机器学习 KNN算法_0 丐版(matlab实现)
- nodejs常用模块-url
- 《PPT高手之道:六步变身职场幻灯派》一0.4 PPTology的3大阶段、6个步骤、24个模块...
- java 网络实验_20145220 实验五 Java网络编程
- git切换分支出现head is now at_git寻根——^和~的区别
- GUI实现学生点名系统
- 程序员至少一半时间用于测试
- python基本语法总结(超级全面,细致,只用一周就可以入门python到实践),会持续更新
- 高中数学学习技巧,这几步你都做到了吗?
- 华为鸿蒙系统手机会卡吗,鸿蒙系统的手机,会像安卓一样越来越卡吗?
- 装饰装修类小程序开发