Java 基础整理(一)

344 阅读4分钟

这是我参与更文挑战的第 1 天,活动详情查看: 更文挑战

  1. char可以存储汉字吗,为什么?

    • char是按字符存储的,不管是英文还是中文,固定占用两个字节,用来存储unicode字符,范围在0-65536。

    • unicode :统一的字符编号,仅仅提供字符与编号间映射。符号数量在不断增加,已超百万。unicode编

      字符集中包含了汉字,所以char型变量当然可以存储汉字了,不过,如果某个特殊的汉字没有被包含在

      unicode编码字符集中中就不能存储。如果用3个字节则有很多不常用的字又占用了很多不必要的存储,

      所以我们用2个字节而不是1个或3个表示汉字的国际码。这个特殊汉字。统一的字符编号,详细:[zh.wikipedia.org/zh-cn/Unico…]

    • UTF :unicode转换格式 (unicode transformation format) 。定义unicode中编号的编码方式。utf8和

      utf16便是其中两种实现方式。其中utf8为变长表示,长度可能时1~6个字节;utf16为变长表示,长

      度可能是2或4个字节。详细:UTF8 [zh.wikipedia.org/zh-cn/UTF-8] UTF16 [zh.wikipedia.org/zh-cn/UTF-1…]

    • unicode编码固定占用两个字节,所以,char类型的变量也是占用两个字节。unicode(统一码、万国

      码、单一码)是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进

      制编码,以满足跨语言、跨平台进行文本转换、处理的要求。传统的编码方式存在的缺陷:

      ①在不同的编码方案下有可能对应不同的字母

      ②采用大字符集的语言其编码长度可能不同

      目前的用于实用的 Unicode 版本对应于 UCS-2,使用16位的编码空间。也就是每个字符占用2个字节。

    • 不同的编码占据字节数也不同:utf-32中文是4字节;utf-8码的中文是3字节的,字母是1字节,英文utf-8

      是变长编码。gbk/gbk18030 中文是2字节的,英文是1个字节。

    • **字符集的作用:把字符映射成整数,供计算机识别。**这个映射的整数也叫码点,Java的String中也可以看

      到一些codePoint的相关方法。计算机存储是以utf-16进行编码的(历史原因,65535不够用,这也是第二个要点)

      结论:

      Java char不存utf-8的字节,而是utf-16的

      Unicode 通用字符集占两个字节,例如"中"

      Unicode 扩展字符集需要用一对char来表示,例如"😄"

      Unicode 是字符集,不是编码,作用类似于ASCII码

      Java String的 length 不是字符数,而是char的个数

    Java中 有内码和外码这一区分简单来说

    • 内码:char或String在内存里使用的编码方式。

    • 外码:除了内码都可以认为是“外码”。(包括class文件的编码)

      Java内码:unicode(utf-16)中使用的是utf-16.

      String.length()

      所以上面的那句话再进一步解释就是:返回字符串的长度,这一长度等于字符串中的UTF-16的代码单元的数目。

image-20200406222255180.png

 **String.codePointCount()**用于统计字符串有几个字符。

 参考链接  https://www.nowcoder.com/discuss/359821?type=1  

2. Java初始化顺序

  • 对于静态变量、静态初始化块、变量、初始化块、构造器,它们的初始化顺序依次是:

(静态变量、静态初始化块)>(变量、初始化块)>构造器。同一括号中执行顺序取决于在类中的出现的先后顺序。

  • 子类的静态变量和静态初始化块的初始化是在父类的变量、初始化块和构造器初始化之前就完成了。

    父类--静态变量

    父类--静态初始化块

    子类--静态变量

    子类--静态初始化块

    父类--变量

    父类--初始化块

    父类--构造器

    子类--变量

    子类--初始化块

    子类--构造器

  • 如果调用静态方法, 不会涉及到多态,在哪个类中调用静态方法,优先找本类,否则搜索父类,再搜索父接口,如果在父接口找到则报错。 如果调用实例方法,会动态分派,动态解析,只用实际类型的实例方法。

  • 初始化过程:

    类加载校验:将类 TestLocal 加载到虚拟机

    执行 static 代码块

    为对象分配堆内存

    对成员变量进行初始化(对象的实例字段在可以不赋初始值就直接使用,而局部变量中如果不赋值就直接使用,因为没有这一步操作,不赋值是属于未定义的状态,编译器会直接报错)

    调用初始化代码块

    调用构造器函数(可见构造器函数在初始化代码块之后执行)