深入理解Java基础知识(一)

51 阅读4分钟

林黛玉 半卷湘帘半掩门,碾冰为土玉为盆。

偷来梨蕊三分白,借得梅花一缕魂。

@TOC


前言

本周开始跟着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:

blog.csdn.net/h1130189083…

三.移位运算符

不支持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成员变量存储在哪里:

cloud.tencent.com/developer/a…

二.字符串常量

之所以单独列出来,是因为算法中常考到对应的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的图 在这里插入图片描述 其次,对于编译期和运行期这两点还不能理解到底是什么意思 详细了解:

www.cnblogs.com/eycuii/p/11…

四.可变参数

    public void print1(String... s){
        for(String s1 : s){
            System.out.print(s1);
        }
    }

六.基本数据类型

什么是逃逸分析:

juejin.cn/post/684490…

对于逃逸的局部对象,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;

可以通过字节码来具体过程 详细了解:

www.jianshu.com/p/f97d5880e…

介绍两个重要的类:

        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);