说明:本文章仅用于自己学习,可能有错误的地方,请包涵
基本语法
标识符和关键字的区别
- 标识符是编写程序的时候为类、方法、变量等,取的名字
- 关键字是被Java语言赋予了一些特殊含义的标识符。
Java有哪些关键字
| 分类 | 关键字 | ||||
|---|---|---|---|---|---|
| 访问控制 | private | protected | public |
continue、break和return的区别
这个很简单吧,当然很简单了🥰
- continue 是跳出当前的这一次循环,继续下一次循环;
- break 是跳出整个循环体,执行循环下面的语句;
- 如果是多层循环,则只跳出break语句所在的那一层循环,外层循环继续执行。
- return 是结束程序执行。
基本数据类型和包装类
Java中有几种基本数据类型
也是很简单的题目哦😀
- 6种数字类型
- 4种整数类型:byte、short、int、long;
- 2种浮点类型:fload、double
- 1种字符类型:char
- 1种布尔类型:boolean
这8种基本数据类型的默认值、取值范围及占用空间如下:
| 基本类型 | 位数 | 字节 | 默认值 | 取值范围 |
|---|---|---|---|---|
| byte | 8 | 1 | 0 | -128-127 (, ) |
| short | 16 | 2 | 0 | -32768(-2^15) ~ 32767(2^15 - 1) |
| int | 32 | 4 | 0 | -2147483648 ~ 2147483647 |
| long | 64 | 8 | 0L | -9223372036854775808(-2^63) ~ 9223372036854775807(2^63 -1) |
| char | 16 | 2 | 'u0000' | 0 ~ 65535(2^16 - 1) |
| boolen | 1 | false | true, false |
基本类型和包装类型的区别
Java中的8种基本数据类型都有对应的包装类。包装类型其实就是普通的类。两者之间的区别也可以说是基本数据类型与普通类的区别。
他们的区别主要有:
| 基本类型 | 包装类 | ||
|---|---|---|---|
| 存储位置 | 局部变量中的基本类型,存储在Java虚拟机的局部变量表(栈);成员变量中的基本类型,存储在堆中 | 存储在堆中 | |
| 用途 | 用于定义常量和局部变量 | 包装类型可用于泛型, 集合、方法的传参 | 这个地方保持怀疑,再看下以前的代码 |
| 默认值 | 0或 | NULL | |
| 比较方式 | 可以用 == 比较两个值是否相等 | 用equals方法比较两个对象的值 |
Integer.valueOf源码了解吗
见另一篇文章:Integer.valueOf()源码分析
自动装箱与拆箱
- 装箱:将基本类型用对应的引用类型包装起来
- 其实就是调用包装类的valueOf()方法,new一个包装类对象并返回。
- 如:Integer i = 10 等价于:Integer i = Integer.valueOf(10)(引申,将字符串转为int类型);还有将基本数据类型放入集合中,也会触发基本类型的自动装箱。
- 拆箱:将包装类型转为基本类型
- 其实就是调用包装类的xxValue()方法,直接返回一个基本类型。
- 如:int n = i 等价于:int n = i.intValue();另外基本类型和包装类型比较时,会触发包装类的自动拆箱
当表格中左边列出的基础类型与它们的包装类有如下几种情况时,编译器会自动帮我们进行装箱或拆箱.
- 进行 = 赋值操作(装箱或拆箱)
- 进行+,-,*,/混合运算 (拆箱)
- 进行>,<,==比较运算(拆箱)
- 调用equals进行比较(装箱)
- ArrayList,HashMap等集合类 添加基础类型数据时(装箱)
包装类型的缓存机制
用缓存机制主要是为了提升性能。使用自动装箱(Integer i = 1)方式创建包装类对象时,会先调用valuaOf()方法进行包装类对象的初始化,比如Integer.valueOf()方法,源码里会先判断传入的整数范围是否在-128到127之间,如果是的话,直接从缓存中获取,否则会new一个新的包装类对象并返回。
- Byte、Short、Integer、Long四种数字类型,Java缓存了[-128, 127]之间的数据;
- 其中Integer类型的上界,可以使用 JVM 的启动参数设置最大值。(通过 JVM 的启动参数 -XX:AutoBoxCacheMax=size 修改)
- Character创建了[0,127]范围内的缓存数据;
如果超出上述范围,则仍然需要到堆中创建新的对象。
两种浮点数类型的包装类 Float,Double 并没有实现缓存机制。
缓存的源码如下:
Integer类
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high) {
return IntegerCache.cache[i + (-IntegerCache.low)];
}
return new Integer(i);
}
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() {}
}
System.identityHashCode(Object x)方法可以返回对象的内存地址,不管该对象的类是否重写了hashCode()方法。
数据比较
基本类型和包装类型的比较
两者之间的比较,会触发包装类型的自动拆箱机制,包装类型转为基本类型之后进行比较。所以只要两者的值相同。比较结果就是true。
包装类型与包装类型的比较
“==”比较。因为包装类型缓存机制的存在,所以:
如果比较的数在指定范围内,数值相等,结果就是true。具体的数值缓存范围是这样的:
- Byte、Short、Integer、Long四种数字类型,Java缓存了[-128, 127]之间的数据;
- Character创建了[0,127]范围内的缓存数据;
如果比较的数不在这个范围内,就是两个对象之间的比较,比较的是对象的地址。地址相同则为true,否则为false
“equals”比较。包装类重写了equals方法,比较的是对象的数值,如果数值相同就返回true。
浮点数相关
...
变量
Java有哪些变量类型
- 成员变量:定义在类中,方法之外的变量,可以被类中的方法、代码块使用。可以被访问修饰符修饰
- 实例成员变量:new 对象的时候赋值。通过对象.变量名进行访问。
- 静态成员变量(类变量):定义在类中,方法之外,并且被static关键字修饰。作用域:整个类。在类加载时进行赋值,可以直接通过类.变量名进行访问
- 局部变量:定义在方法中或代码块中,作用于仅限于当前方法或代码块。局部变量必须在使用前声明,而且不能被访问修饰符修饰
- 参数变量:方法定义时声明的变量,调用方法时传入的值,作用域仅限于当前方法
成员变量和局部变量的区别
- 语法:
- 成员变量是定义在类中、方法之外的变量,可以被访问修饰符修饰;
- 实例成员变量跟随对象的存在而存在,需要通过实例对象访问;静态成员变量,要加static关键字修饰,可以直接通过类.变量名进行访问;
- 局部变量是定义在方法或代码块中的变量,不能被访问修饰符修饰。
- 存储区域:实例成员变量存储在堆内存;静态成员变量在jdk8以后存储在堆中?;局部变量存储在虚拟机栈的局部变量表中
- 作用域和生命周期:
- 成员变量可以被类中的任意方法使用;
- 局部变量的作用域只有当前方法或代码块;
- 静态成员变量跟类的生存周期一样;实例成员变量跟对象的生存周期一样。
- 默认值:
- 成员变量如果没有手动赋值,会自动以类型的默认值进行赋值
- 局部变量不会自动赋值,在使用前必须赋值
public class Variables {
public static Integer j;
public static void main(String[] args) {
Integer i;
// 成员变量没有赋值就使用,编译会报错
System.out.println(i);
// 没有手动赋值,会给一个默认值null
System.out.println(j);
}
}
字符型常量和字符串常量的区别
- 定义:字符型常量是单引号括起来的一个字符;字符串常量是双引号括起来的0个或多个字符
- 含义:字符型常量就是ASCII值,可以直接参与+-运算:字符串常量是一个地址值
- 占用内存大小:在Java中,1个字符占2字节;字符串占多个字节;