Java知识复习(前篇)

内置数据类型

  • byte/8
  • char/16
  • short/16
  • int/32
  • float/32
  • long/64
  • double/64
  • boolean/~

boolean比较特殊,只有true和false,可以单位存储,但不是规定。JVM编译时会将boolean类型转为int类型,1=true,0=false。JVM支持boolean数组,但是是通过读写byte数组实现。

包装类型–引用数据类型(含相应内置数据类型)

  • Byte:byte
  • Character:char
  • Short:short
  • Integer:int
  • Float:float
  • Long:long
  • Double:double
  • Boolean:boolean

装箱||拆箱

装箱

具体是指将基本类型转化为包装类型。具体做法是通过调用valueOf方法实现的。例如,将char转型为Character类型调用的就是Character.valueOf()。在valueOf的执行上表现为,按类型分类:

  1. 整数类型:若在常用取值范围内(即在缓冲池中),则直接返回该对象的引用,否则创建一个新的对象并返回它的引用。
  2. 浮点类型:创建新对象并返回引用。
  3. 布尔类型:直接返回静态常量true||false

代码举例:

	Character c = "c";

拆箱

指将包装类型转换为基本类型。具体做法是通过包装类型的xxxValue方法来实现转换。

代码举例:

	Character c = "c";
	char a = c;

自动装箱与手动装箱

手动装箱是指显式调用new的方式经行装箱,例如:

	Character c = new Character("c");

自动装箱指用字面值代替显示调用new的方式进行装箱,这种方式是jdk 1.5之后出现的特性,例如:

	Character c = "c";

区别:手动装箱每次创建新对象,自动装箱会先判断缓冲池中是否存在该字面量,若有则直接返回它的引用,若无再创建新对象。在 Java 8 中,Integer 缓存池的大小默认为 -128~127。

资料:在 jdk 1.8 所有的数值类缓冲池中,Integer 的缓冲池 IntegerCache 很特殊,这个缓冲池的下界是 - 128,上界默认是 127,但是这个上界是可调的,在启动 jvm 的时候,通过 -XX:AutoBoxCacheMax= 来指定这个缓冲池的大小,该选项在 JVM 初始化的时候会设定一个名为 java.lang.IntegerCache.high 系统属性,然后 IntegerCache 初始化的时候就会读取该系统属性来决定上界。

String

基本概要

String 被声明为final,也就是说无法被继承,所有的包装类型也无法被继承。当前String内部存储字符串的方式是使用带final关键字的byte数组,因此还带有coder标识来识别编码方式。由于存储字符串的数组是final修饰的,无法被修改,也就意味着String对象一旦被创建就无法被改变。不改变就意味着有几个好处:

  1. 可以缓存hash值
  2. String Pool 的需要
  3. 线程安全
  4. 网络传输安全

String与StringBuffer和StringBuilder

StringStringBufferStringBuilder
可变性不可变可变可变
线程安全性线程安全线程安全线程不安全

String pool

字符串常量池保存所有的字符串字面量,字符串池由String类私有的维护, 在创建String对象的时候有两种创建方式,两种的性能不大相同:

  1. 采用new的方式初始化,例如:
    	String a = new String("a");
    
    这种方法的执行过程如下,JVM首先拿着"a"这个字符串去String pool里面找,如果没找到,就先在池里新建一个”a“对象然后再去堆里新建一个”a"字符串对象,再把堆里的字符串对象的引用返回;如果找到了,pool和JVM相视一笑,JVM就直接在堆里创建"a"字符串对象并返回它的引用。
  2. 采用字面量直接赋值的方法,例如:
    	String a = "a";
    
    这种方法会让JVM先带着”a"去pool里面找有没有一样的,如果找到了就直接返回pool里的字符串对象的引用;如果找不到,JVM只能长叹一声然后在pool里创建一个新的”a"字符串对象并返回它的引用。

参数传递

重点

Java参数是按值传递,不是引用传递。传对象的时候实际传递的是这个对象的地址。(我理解的就是进去的东西只是一个指针,调用对象的方法的时候会自动解引用)因此,在函数内对传进来的对象进行修改如果是使用 ” . “ 的方式(使用方法或直接修改【这不封闭】)可以修改成功。若是使用 ”=“的方式,只是把形参的值(形参存地址)换了一个,外面的实参没动,实参的值不变(存的地址不变)。
举例:

public class PassByValueExample {
    public static void main(String[] args) {
        Dog dog = new Dog("A");
        System.out.println(dog.getObjectAddress()); // Dog@4554617c
        func(dog);
        System.out.println(dog.getObjectAddress()); // Dog@4554617c
        System.out.println(dog.getName());          // A
    }

    private static void func(Dog dog) {
        System.out.println(dog.getObjectAddress()); // Dog@4554617c
        dog = new Dog("B");
        System.out.println(dog.getObjectAddress()); // Dog@74a14482
        System.out.println(dog.getName());          // B
    }
}

类型转换

基本概要

Java 不支持隐式向下转型,不允许精度降低的自动操作。

float 与double的恩怨

首先,字面量的浮点数,都是double类型的。这就导致了float不能直接写字面量赋值,即下面的例子是失败的:

	float a = 1.1;// 跑不动

那要想成功怎么办,让字面量f:

	float a = 1.1f;// 冲

智能整数

字面量的整数,很有意思,会根据字面量的大小是不是在整数类型的取值范围内来判断这个语句是否有类型转换的问题,举个例子,下面的代码数值在short的取值范围内:

	Short a = 1;// 可以跑

下面的不在取值范围内:

	Short a = 32768; // 不行

switch

基本概要

Java的switch支持了一个非常令人激动的特性,可以在条件判断中使用字符串类型,哦我的上帝,真令人高兴。同时switch是不支持long的,因为设计switch的时候就没想过可能会有那么case,如果有,那一定是神仙。有复杂的值需要判断,这边建议您用if。

关键字

final

一言以蔽之,不许动。

  1. 修饰数据:这个变量名所代表的内存里面的东西不能变,但是这个内存里面的东西所指向的另一个内存里的东西是可以的,也就是说用final修饰了一个引用,这个引用就不能二婚,不能指向别的对象,但你的对象依旧是自由的,它可以变。
  2. 修饰方法:你可以把它看作是private,也就是无法继承,实际上private被隐式的指定为final了。如果你硬要杠,偏要继承后写个一摸一样的方法,那这个方法是新方法,而不是重写的。
  3. 修饰类:不准继承,绝后了。

static

  1. 修饰变量(也叫静态变量,下面的一样):被修饰的变量将会是整个类一起共享的,而不是单个对象独占的,内存中就一份,不管这个类你创建了多少对象。实例变量(没有static修饰变量的都是)也好说,就是每个对象自己的,几个对象就几个实例变量。

  2. 修饰方法:同样,被修饰的方法是整个类共有的,但是,这个方法里面只能有静态变量,必须有方法体,不能有this和super。

  3. 修饰语句块:整个类共有,只在类初始化的时候运行一次。

  4. 修饰内部类:非静态内部类需要依赖外部实例,没有外部实例就不能创建,有了外部实例后使用"外部实例.new 内部类()"的格式创建内部类,不限量。静态内部类不依赖外部实例,可以自由创建。

  5. 静态导包:在使用静态变量和方法时不用再指明 ClassName,从而简化代码,但可读性大大降低,举例:

    package a;// 提供静态内部类
    
    /**
     * @author ZTL
     */
    public class JavaBlogTest {
        public static class MyInnerClass {
        }
        public static void main(String[] args) {
            MyInnerClass a = new MyInnerClass();
            MyInnerClass b = new MyInnerClass();
        }
    }
    
    package b;// 消费静态内部类
    
    import static a.JavaBlogTest.*;
    
    /**
     * @author ZTL
     */
    public class JavaBlogTest2 {
        public static void main(String[] args) {
            MyInnerClass a = new MyInnerClass();
        }
    }
    

类内变量和方法初始化顺序

  • 初始化顺序:存在继承的情况下的初始化顺序,越靠前越早初始化。
    • 父类(静态变量、静态语句块)
    • 子类(静态变量、静态语句块)
    • 父类(实例变量、普通语句块)
    • 父类(构造函数)
    • 子类(实例变量、普通语句块)
    • 子类(构造函数)
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值