刚毕业那会出来面试,端端正正坐在面试官前面,微笑着看着他,面试官也微笑着看着我。
面试官:看你刚毕业,我来考考你一些Java基础问题吧。
我:好!(心中狂喜,Java基础也准备了好久)
面试官:你来写一下八大基础数据类型吧
我心想:(啥?八大基础类型?那不是我大一学的吗?都有啥来着?)
我:我凭着记忆力写下了Integer,String,Double,Float,Long....额,还有几个不记得了...
面试官还是微笑着看着我:你确定你写的这些都有吗?
我:(为了表现出自己的自信说到)这几个我还是确定的...其他的几个不记得了
面试官沉思了下说到:好的,我知道了,那今天面试就到这里了,你先回去等结果吧。
我:????(我花了两小时才过来,面试不到2分钟,就结束了?)
然后他就出去了,接着我就被人事带出了门....然后就没有然后了...
回去的路上怎么想都不对劲,回到家中查了下才发现我错的离谱,好家伙,我把学的知识都还回去了!!
于是那次面试成了我一辈子的痛!!后来整理相关资料发现里面可以深挖的点确实比较多,于是便有了今天的文章。
一、八大基础数据类型
这个知识点我要记一辈子!!!o(╥﹏╥)o
- 整型:byte, short, int, long
- 字符型:char
- 浮点型:float, double
- 布尔型:boolean
①、byte
二进制位数:8
包装类:java.lang.Byte
最小值:Byte.MIN_VALUE= -128(-2^7)
最大值:Byte.MAX_VALUE= 127(2^7-1)
默认值:0
相关测试用例:
byte a = 127;
byte b = 1;
a += b;
//a = a + b; //强制类型提升造成直接报错
结果:a = -128
//-------------------------------
byte a = 127;
byte b = 127;
a += b;
结果:a = -2
//负数在现代计算机里一般用补码表示:最高位是符号位,其余位为数字的原码取反+1。
//1000 0000还原为原码:最高位是1,表示负数,
//剩余的各位取反 111 1111 再+1 得到 1000 0000, +128的原码,整个数为-128
“+=”是java中的一个运算符,而不是两个,所以在运算时 会进行自动类型转换,也就是低级变量可以直接转换为高级变量。所以在编译时没有报错。
②、short
二进制位数:16
包装类:java.lang.Short
最小值:Short.MIN_VALUE = -32768(-2^15)
最大值:Short.MAX_VALUE = 32767(2^15 - 1)
默认值:0
③、int
二进制位数:32
包装类:java.lang.Integer
最小值:Integer.MIN_VALUE= -2,147,483,648(-2^31)
最大值:Integer.MAX_VALUE= 2,147,483,647(2^31 - 1)
默认值:0
int和Integer的区别
- Integer是int的包装类;int是基本数据类型;
- Integer变量必须实例化后才能使用;int变量不需要;
- Integer实际是对象的引用,指向此new的Integer对象;int是直接存储数据值 ;
- Integer的默认值是null;int的默认值是0。
④、long
二进制位数:64
包装类:java.lang.Long
最小值:Long.MIN_VALUE=-9,223,372,036,854,775,808(-2^63)
最大值:Long.MAX_VALUE=9,223,372,036,854,775,807(2^63 -1)
默认值:0L
注意:"L"理论上不分大小写,但是若写成"l"容易与数字"1"混淆,不容易分辩。所以最好大写。
⑤、float
二进制位数:32
包装类:java.lang.Float
最小正非零值:Float.MIN_VALUE=1.4E-45 (2^-149)(正数)
最大值:Float.MAX_VALUE=3.4028235E38 (2^128 - 1)
默认值:0.0f
|-------- 31 -------|------------ 30-23 ------------ |------------ 22-0 ------------|
符号位(sign) 指数部分(exp) 小数部分(mag)
- sign:符号位就一位,0表示正数,1表示负数
- exp: 指数部分,无符号正数
- mag:小数部分,定点小数,小数点在最左边。
- float的表达式 : pow(-1,sign) * (1+mag) * pow(2,exp-127)
⑥、double
二进制位数:64
包装类:java.lang.Double
最小正非零值:Double.MIN_VALUE=4.9E-324 (2^-1074)(正数)
最大值:Double.MAX_VALUE=1.7976931348623157E308 (2^1024 - 1)
默认值:0.0d
float 和int 都是4字节,但是最大值却比long还要大很多,因为 整数在计算机底层采用补码的形式表示,除去首位的符号位,剩余的位数即表示数值的范围,也就是位数越多,范围越大。
float和double才用的是IEEE754浮点数标准
IEEE754标准包含一组实数的二进制表示法。它有三部分组成:
- 符号位
- 指数位
- 尾数位
java中常数默认是int类型的,所以一个常数不能超过Interger.MAX_VALUE,你在定义 long w=12345678901; 时会报错,是因为这个常数已经超过了Int类型能够表示的最大数,所以在定义long类型时,需要在常数后面加 l 或者 L
⑦、boolean
包装类:java.lang.Boolean
默认值:false
只有两个取值:true 和 false;
boolean数据类型表示一位的信息;
⑧、char
二进制位数:16
包装类:java.lang.Character
最小值:\u0000(即为 0)
最小值:\uFFFF(即为65535)
char ch = 'a';
// Unicode 字符表示形式
char uniChar = '\u039A';
// 字符数组
char[] charArray ={ 'a', 'b', 'c', 'd', 'e' };
转义序列
前面有反斜杠(\)的字符代表转义字符,它对编译器来说是有特殊含义的。下面列表展示了Java的转义序列:
转义序列 | 描述 |
\t | 在文中该处插入一个tab键 |
\b | 在文中该处插入一个后退键 |
\n | 在文中该处换行 |
\r | 在文中该处插入回车 |
\f | 在文中该处插入换页符 |
\' | 在文中该处插入单引号 |
\" | 在文中该处插入双引号 |
\\ | 在文中该处插入反斜杠 |
Character 有以下方法:
序号 | 方法与描述 |
1 | 是否是一个字母 |
2 | 是否是一个数字字符 |
3 | 是否是一个空白字符 |
4 | 是否是大写字母 |
5 | 是否是小写字母 |
6 | 指定字母的大写形式 |
7 | 指定字母的小写形式 |
8 | toString() 返回字符的字符串形式,字符串的长度仅为1 |
二、包装类型
为了编程的方便引入了基本数据类型,但是为了能够将这些基本数据类型当成对象操作,Java为每一个基本数据类型都引入了对应的包装类型(wrapper class),int的包装类就是Integer,从Java 5开始引入了自动装箱/拆箱机制,使得二者可以相互转换。
基本数据类型: boolean,char,byte,short,int,long,float,double
封装类类型:Boolean,Character,Byte,Short,Integer,Long,Float,Double
三、自动装箱和自动拆箱
①、自动装箱:将基本数据类型重新转化为对象
// 声明一个Integer对象,用到了自动的装箱:
//解析为:Integer num = Integer.valueOf(9);
Integer num = 9;
9是属于基本数据类型的,原则上它是不能直接赋值给一个对象Integer的。但jdk1.5后你就可以进行这样的声明,自动将基本数据类型转化为对应的封装类型,成为一个对象以后就可以调用对象所声明的所有的方法。
②、自动拆箱:将对象重新转化为基本数据类型
/ /声明一个Integer对象
Integer num = 9;
// 进行计算时隐含的有自动拆箱
System.out.print(num--);
因为对象是不能直接进行运算的,而是要转化为基本数据类型后才能进行加减乘除。
四、重点
①、Integer比较相关
Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
Integer e = -128;
Integer f = -128;
Integer g = -129;
Integer h = -129;
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(a == b);//true
System.out.println(c == d);//false
System.out.println(e == f);//true
System.out.println(g == h);//false
System.out.println(i == j);//false
归结于java对于Integer与int的自动装箱与拆箱的设计,是一种模式:叫享元模式(flyweight)。
(1)加大对简单数字的重利用,Java定义在自动装箱时对于在-128~127之内的数值,它们被装箱为Integer对象后,会存在内存中被重用,始终只存在一个对象。
(2)而如果在-128~127之外的数,被装箱后的Integer对象并不会被重用,即相当于每次装箱时都新建一个 Integer对象。
所以Integer比较的时候尽量用对象的equals方法,因为Integer中重写了equals方法
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
源码分析:
当给一个Integer对象赋一个int值的时候,会调用Integer类的静态方法valueOf
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);
}
/**
* 缓存支持自动装箱的对象标识语义 -128和127(含)。
* 缓存在第一次使用时初始化。
* 缓存的大小可以由-XX:AutoBoxCacheMax = <size>选项控制。
* 在VM初始化期间,java.lang.Integer.IntegerCache.high
* 属性可以设置并保存在私有系统属性中
*/
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) {
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);
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++) {
cache[k] = new Integer(j++); // 创建一个对象
}
}
private IntegerCache() {}
}
☆②、计算斐波那契数列(0、1、1、2、3、5、8、13、21、34、……)第n项的值
这个数列从第3项开始,每一项都等于前两项之和。这道题当年面试的时候没有考虑到最大值的情况,直接使用int去实现,结果.......面试跪了!!😢
经我测试,当 value = 92,结果为:7540113804746346429,该值超过了long的最大值,这时可以改用BigInteger类型去实现,代码如下:
@JvmStatic
fun main(args: Array<String>) {
println("请输入一个数:")
val reader = BufferedReader(InputStreamReader(System.`in`))
val num = reader.readLine().toInt()
val answer = fibonacciTest(num)
println("第${num}个斐波那契数为:$answer")
}
private fun fibonacciTest(value: Int): BigInteger {
if (value < 2) return BigInteger(value.toString())
var first = BigInteger("0")
var second = BigInteger("1")
var temp = BigInteger("0")
for (i in 2..value) {
temp = first.add(second)
first = second
second = temp
}
return temp
}
就是以上这些,待我发现新的易错的知识点再来补充~