java基础——有多少是你不知道的?
- 一、&&和||
- 二、Integer和int
- 三、String、StringBuffer、StringBuilder的区别
- 四、i+1<i居然是成立的?
- 五、一脸懵逼的null问题
- 六、整数除法向上取整你知道多少种?
- 七、这也能运行?
一、&&和||
1、下面的程序你猜会打印什么呢?
结果为以下:
2、解释
&&符号当左边为false的时候就不再执行右边的判断了,因为程序已经可以确定为false了,所以b++并没有执行
||符号当左边为true的时候就不在执行左边的判断了,因为程序已经可以确定为true了,所以d++被执行了
3、这种判断机制的用途
可以解决先后判断问题,例如以下程序
先判断非空再判断字符串长度是没有错的,因为s为空的时候,就不会去执行s.length()==5
反过来,先判断字符串长度的话会立马抛出空指针异常
二、Integer和int
1、下面的题你能做对吗?输出结果是什么呢?
结果:
2、解释
Integer是int的包装类,Integer引用的是堆内存新建的对象,int引用的是java常量池里的数据
Integer和int会有拆箱装箱机制
int和Integer比较时,Integer会自动拆箱为int
int赋值Integer数据时,Integer会自动拆箱为int
Integer赋值int数据时,int会自动装箱为Integer
int和int用==比较时,比较的是值的大小
int和Integer用==比较时,Integer会自动拆箱为int,比较的是值的大小
Integer和Integer用==比较时,比较的是两个对象是否是同一个的引用
int自动装箱的小细节:对于-128~127的数据,int会判断缓存里有没有相对应值的Integer对象,如果有,直接返回该对象,否则新创建一个对象,并把对象放到缓存中。这样做是为了对于频繁使用的数据只保存一份数据,减少内存的浪费
package com.wu.hello.main;
public class Main {
public static void main(String[] args) {
int a=0;
int b=0;
// true,int和Integer用==比较时,Integer会自动拆箱为int,比较的是值的大小
System.out.println(a==b);
Integer c=new Integer(1);
Integer d=new Integer(1);
// false,Integer和Integer用==比较时,比较的是两个对象是否是同一个的引用
System.out.println(c==d);
Integer e=2;
Integer f=2;
// true,int自动装箱的小细节:对于-128~127的数据,int会判断缓存里有没有相对应值的Integer对象,
// 如果有,直接返回该对象,否则新创建一个对象,并把对象放到缓存中。
System.out.println(e==f);
Integer g=200;
Integer h=200;
// false,int自动装箱的小细节:对于-128~127的数据,int会判断缓存里有没有相对应值的Integer对象,
// 如果有,直接返回该对象,否则新创建一个对象,并把对象放到缓存中。
System.out.println(g==h);
Integer i=new Integer(200);
int j=new Integer(200);
// true,int和Integer用\=\=比较时,Integer会自动拆箱为int,比较的是值的大小
System.out.println(i==j);
}
}
三、String、StringBuffer、StringBuilder的区别
1、区别
String | StringBuffer | StringBuilder | |
---|---|---|---|
内存位置 | java常量池/堆空间 | 堆空间 | 堆空间 |
线程安全问题 | 线程安全 | 线程安全 | 线程不安全 |
是否可变 | 不可变 | 可变 | 可变 |
效率 | 最慢 | 一般 | 最快 |
使用场景 | 不需要更改时使用 | 多线程 | 单线程 |
2、String是不可变的是什么意思?
例如字符串s=“abc”,如果想要s=“adc”,不可以直接把字符 ‘b’ 修改为 ‘d’ ,而要新创建一个对象"adc",让s去引用它
3、String为什么是最慢的?
因为String对象是不可变的,每次修改的时候都需要产生一个新的对象
例如字符串拼接:“abc”+“d”,需要新创建一个字符串对象"abcd",而StringBuffer和StringBuilder可以直接修改当前对象
4、什么线程不安全?
在多线程的情况下会出现错误,例子:多个线程同时修改StringBuilder对象
package com.wu.hello.main;
public class Main {
public static void main(String[] args) throws InterruptedException {
StringBuilder s=new StringBuilder();
for (int i = 0; i < 10; i++){
new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 1000; j++){
s.append("a");
}
}
}).start();
}
Thread.sleep(1000);
System.out.println(s.length());
}
}
报了异常,按道理应该输出10000的,因为多线程问题,使得结果发生了错误,这就是线程不安全
5、StringBuilder线程不安全的原因
因为多个线程操作的是同一个StringBuilder对象,而StringBuilder的方法调用时没有加锁,导致多个线程同时进入方法,出现不一致问题,例如线程1进入方法后获取了数据,线程2修改了字符串,那么线程1拿到的就是脏数据
而StringBuffer的每个方法是加了synchronized的,所以多线程是没问题的
6、同样地,HashMap 、HashSet都是非线程安全的,如果在多线程环境下,可以使用 ConcurrentHashMap、ConcurrentHashSet来代替,当然效率也会降低一些
四、i+1<i居然是成立的?
1、笔试题:是否存在数字 i+1<i?存在吗?
在计算机里面是存在的,Int类型的数占32位,当int是最大值的时候,再加1,那么就会变为最小值
package com.wu.hello.main;
public class Main {
public static void main(String[] args) throws InterruptedException {
int maxValue = Integer.MAX_VALUE;
System.out.println(maxValue);
System.out.println(maxValue+1<maxValue);
}
}
五、一脸懵逼的null问题
1、先看程序
package com.wu.hello.main;
public class NULL {
public static void haha(){
System.out.println("haha");
}
public static void main(String[] args) throws InterruptedException {
((NULL)null).haha();
}
}
2、这嘛玩意?这个程序真的可以跑的吗?真的!
3、解释
其实NULL是类的名字,在java里面,null可以转成任何对象。转了之后也就相当于以下程序:
package com.wu.hello.main;
public class NULL {
public static void haha(){
System.out.println("haha");
}
public static void main(String[] args) throws InterruptedException {
NULL n=null;
n.haha();
}
}
所以,你大概懂了吧!haha()是static方法,null对象同样可以调用!当然的,不是static方法的话就会报空指针异常了
六、整数除法向上取整你知道多少种?
package com.wu.hello.main;
public class Main {
public static void main(String[] args) {
int a=20;
int b=6;
//方法1
System.out.println((int)Math.ceil((double) a/b));
//方法2
System.out.println(a/b+(((a%b)!=0)?1:0));
//方法3
System.out.println((a+b-1)/b);
}
}
最常用的向上取整就是方法3啦
七、这也能运行?
1、先看程序
package com.wu.hello.main;
public class Main {
public static void main(String[] args) {
https://www.baidu.com/;
System.out.println("haha");
}
}
2、你觉得这个程序可以运行吗?
答案是可以滴
3、解释
实际上的程序是这样的:
package com.wu.hello.main;
public class Main {
public static void main(String[] args) {
https:
System.out.println("haha");
}
}
实际上https: 是goto语句的写法,这种写法已经快被弃用了,原因是goto语句会使程序变得杂乱无章,程序维护困难。
可以看以下程序理解goto用法:
package com.wu.hello.main;
public class Main {
public static void main(String[] args) {
https:
while (true){
break https;
}
System.out.println("haha");
}
}
java对c++的goto语法做了优化,只能接在break、continue后面,跳出循环或者是重新执行循环
觉得写得不错就点个赞吧!