半卷湘帘半掩门,碾冰为土玉为盆。
偷来梨蕊三分白,借得梅花一缕魂。
2023-3-1第一次编辑
前言
本周开始跟着JAVAGuide学习Java基础,感谢Guide哥!欢迎大家一起讨论学习!
提示:以下是本篇文章正文内容,下面案例可供参考
一. JVM和JDK和JRE
JDK>JRE>JVM
JDK包含JRE,编译器javac和工具javadoc
JRE包含JVM,Java命令,Java类库
JVM包含,堆内存,栈内存等
二.从.class到源码
JVM会通过类加载器将.class文件变成机器码。
注意:字节码不分操作系统,也就是只有一种,但是JVM却是根据不同操作系统有不同的区别。因此也就有了“一次编译,随处运行”
但是对于那些经常调用的那些内容,这么做明显会减慢代码执行的速度。
因此后面引进JIT,属于运行时编译,也就是在一次从class文件变成机器码后,这一部分跟传统的JVM一样,但是会保留它对应的机器码,那么下次调用的时候,就会自动的识别出机器码,不需要解释器的帮助了。
因为先用javac编译成字节码,然后再解释成机器码。它跟编译型语言和解释型语言的语言特性都不同。这样也就解释了JAVA是编译和解释并存的语言了。
详细了解AOT和JIT:
https://blog.csdn.net/h1130189083/article/details/78302502
三.移位运算符
不支持float,double类型移位
int i = 2; // 010
int j = 4; // 100
System.out.println(i << 2);// 向左移动两位
System.out.println(i ^ j);// 110,异或
System.out.println(Integer.toBinaryString(i ^ j));// 输出二进制
System.out.println(i << 34); // 实际是34%32=2,结果也是8
四.变量
这是个经常被忽视的细节
一.成员变量和局部变量
要从根本上区分,局部变量属于方法内、参数、代码块中,并且不允许被static静态化,因为它不属于类,它只能存在于栈内存中。其次,它也不能被控制修饰符private,public等所影响。而且它没有默认值,必须由用户赋值,否则不通过
而成员变量则分成两种情况,由于它允许被static,那么当它被static的时候,那么它就是属于类的,那么它存储在方法区(一种说法是方法区也算堆中);反之,它则是属于实例的,被存储在堆内存中。并且它有默认值。
class AClass{
public int a;
}
main(){
AClass aClass = new AClass();
System.out.println(aClass.a);// 编译不会报错
String k;
// System.out.println(k); // 编译会报错
}
详细了解static成员变量存储在哪里:
https://cloud.tencent.com/developer/ask/sof/54024
二.字符串常量
之所以单独列出来,是因为算法中常考到对应的ASCII值的转换
一个字符常量就是一个整型值,可以参与运算,占用两个字节
char c = 'A';
char c2 = 'a';
System.out.println((c + 32) == c2);
System.out.println(97 == c2);
System.out.println((char)97); // 变成小a
五.方法
一.静态方法
从时间的角度来看,静态方法不允许访问非静态变量,那是因为无论是静态方法和静态变量都属于类,在JVM类加载的时候便存在了,比实例化更快,所以是访问不到的。
二.重载
重载是同一个方法的不同实现,Java规定方法名+参数来区分一个方法,因此想要重载,就得保证方法名不变,但是参数需要不同(包括顺序,个数)。构造方法也可以
注意:仅仅返回类型不同是不能算重载
public int add(String b,int a){
return 1;
}
// 会报错
public String add(String b,int a){
return "123";
}
// 改变顺序可以
public int add(int a,String b){
return 2;
}
三.重写
发生在子类和父类之间,方法名和参数名需要相同。构造方法无法被重写,因为方法名不同。
如果修饰符是private/final
,子类则不能重写。对于static也是,目前这点还不能理解为什么
这里还要注意,对于返回的类型,是可以稍微改变的,那么按照这种理解,能改变的一定是引用类型
这里放一张javaguide的图
其次,对于编译期和运行期这两点还不能理解到底是什么意思
详细了解:
https://www.cnblogs.com/eycuii/p/11461535.html
四.可变参数
public void print1(String... s){
for(String s1 : s){
System.out.print(s1);
}
}
六.基本数据类型
什么是逃逸分析:
https://juejin.cn/post/6844903639308304397
对于逃逸的局部对象,JVM将它存储在栈上,而不是存储在堆上
包装类型的缓存机制
// 这样子的方式就适合,但是超过这个值[-127,128]就不会复用已有对象
// Integer integer1 = 3;
// Integer integer2 = 3;
// 这样子方式不适合,只能用equals才能成功比对
Integer integer1 = new Integer(12);
Integer integer2 = new Integer(12);
if (integer1 == integer2)
System.out.println("integer1 == integer2");
else
System.out.println("integer1 != integer2");
Integer integer3 = 300;
Integer integer4 = 300;
if (integer3 == integer4)
System.out.println("integer3 == integer4");
else
System.out.println("integer3 != integer4");
自动拆装箱
// 自动装箱和拆箱
Integer i1 = 100;
int i2 = i1;
可以通过字节码来具体过程
详细了解:
https://www.jianshu.com/p/f97d5880eaa5
介绍两个重要的类:
System.out.println(1.01 + 2.02);// 得到的不是3.03
BigDecimal bigDecimal = new BigDecimal("1.01");
System.out.println(bigDecimal.add(new BigDecimal("2.02")));
BigInteger bigInteger = new BigInteger(String.valueOf(Long.MAX_VALUE) + 2);
System.out.println(bigInteger);