02_基础加强
Static
静态,用来修饰成员变量、成员方法。
修饰成员变量之后称为静态成员变量(类变量),修饰方法之后称为静态方法(类方法)
类变量
static修饰后的成员变量属于类、加载一次,内存中只有一份,可以被类的所有对象共享(访问、修改):
类名.静态成员变量(推荐)
对象.静态成员变量(不推荐)。
实例成员变量(无static修饰,属于对象),访问格式:对象.实例成员变量
public class User {
static String name;
int age;
}
类方法
-
静态成员方法(有static修饰,归属于类),建议用类名访问,也可以用对象访问。
- 静态方法只能访问静态的成员,不可以直接访问实例成员。
- 静态方法中是不可以出现this关键字的。
-
实例成员方法(无static修饰,归属于对象),只能用对象触发访问
应用
工具类
类中都是一些静态方法,每个方法都是以完成一个共用的功能为目的。
好处:一次编写,处处可用,提高代码的重用性
要求:建议工具类的构造器私有化处理,工具类不需要创建对象。
代码块
代码块是类的5大成分之一(成员变量、构造器,方法,代码块,内部类),定义在类中方法外。
在Java类下,使用 { } 括起来的代码被称为代码块 。
- 静态代码块
- 格式:static
- 特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发、只执行一次
- 使用场景:在类加载的时候做一些静态数据初始化的操作,以便后续使用。
- 构造代码块(了解,见的少):
- 格式:
- 特点:每次创建对象,调用构造器执行时,都会执行该代码块,并且在构造器前执行
- 使用场景:初始化实例资源。
单例模式
保证系统中,某个类永远只有一个实例,即一个类永远只能创建一个对象。
例如任务管理器对象我们只需要一个就可以解决问题了,这样可以节省内存空间。
-
饿汉式
在用类获取对象的时候,对象已经提前为你创建好了。
定义一个类,把构造器私有。
定义一个静态变量存储一个对象。
/** a、定义一个单例类 */ public class SingleInstance { /** c.定义一个静态变量存储一个对象即可 :属于类,与类一起加载一次 */ public static SingleInstance instance = new SingleInstance(); /** b.单例必须私有构造器*/ private SingleInstance (){ System.out.println("创建了一个对象"); } }
-
懒汉式
在真正需要该对象的时候,才去创建一个对象(延迟加载对象)。
定义一个类,把构造器私有。
定义一个静态变量存储一个对象。
提供一个返回单例对象的方法。
/** 定义一个单例类 */ class SingleInstance{ /** 定义一个静态变量存储一个对象即可 :属于类,与类一起加载一次 */ public static SingleInstance instance; // null /** 单例必须私有构造器*/ private SingleInstance(){} /** 必须提供一个方法返回一个单例对象 */ public static SingleInstance getInstance(){ ... return ...; } }
继承
概述
Java中提供一个关键字extends,用这个关键字,我们可以让一个类和另一个类建立起父子关系。
public class Student extends People {}
Student称为子类(派生类),People称为父类(基类 或超类)。
作用:当子类继承父类后,就可以直接使用父类公共的属性和方法了,提高代码的复用性
设计规范:子类们相同特征(共性属性、共性方法)放在父类中定义,子类独有的的属性和行为应该定义在子类自己里面。
内存分配:
特点
- 子类可以继承父类的属性和行为,但是子类不能继承父类的构造器
- Java是单继承模式:一个类只能继承一个直接父类。
- Java不支持多继承、但是支持多层继承。
- Java中所有的类都是Object类的子类。
注意:
-
子类可以继承父类的私有成员,只是不能直接访问
-
子类是否可以继承父类的静态成员
有争议的知识点,子类可以直接使用父类的静态成员
成员访问方式
子类方法中访问成员(成员变量、成员方法)满足就近原则
- 先子类局部范围找
- 然后子类成员范围找
- 然后父类成员范围找,如果父类范围还没有找到则报错。
如果子父类中,出现了重名的成员,会优先使用子类的,此时如果一定要在子类中使用父类的怎么办?
可以通过super关键字,指定访问父类的成员:super.父类成员变量/父类成员方法
方法重写
在继承体系中,子类出现了和父类中一模一样的方法声明,我们就称子类这个方法是重写的方法。
应用场景:当子类需要父类的功能,但父类的该功能不完全满足自己的需求时。
重写注解@Override
- @Override是放在重写后的方法上,作为重写是否正确的校验注解。
- 加上该注解后如果重写错误,编译阶段会出现错误提示。
- 建议重写方法都加@Override注解,代码安全,优雅!
注意:
- 重写方法的名称、形参列表必须与被重写方法的名称和参数列表一致。
- 私有方法不能被重写。
- 子类重写父类方法时,访问权限必须大于等于父类 (暂时了解 :缺省 < protected < public)
- 子类不能重写父类的静态方法
构造器
子类中所有的构造器默认都会先访问父类中无参的构造器,再执行自己:
子类初始化之前,一定要调用父类构造器先完成父类数据空间的初始化
调用方式:子类构造器的第一行语句默认都是:super(),不写也存在。
注意:如果父类中没有无参数构造器,只有有参构造器,会出现什么现象呢?
子类会编译报错,因为子类默认是调用父类无参构造器的。
如何解决?
子类构造器中可以通过书写 super(…),手动调用父类的有参构造器。
this与super
访问成员变量 | 访问成员方法 | 访问构造方法 | |
---|---|---|---|
this | this.成员变量 访问本类成员变量 |
this.成员方法(…) 访问本类成员方法 |
this(…) 访问本类构器 |
super | super.成员变量 访问父类成员变量 |
super.成员方法(…) 访问父类成员方法 |
super(…) 访问父类构造器 |
注意:this(…) super(…) 都只能放在构造器的第一行,所以二者不能共存在同一个构造器中。
包
-
包是用来分门别类的管理各种不同类的,类似于文件夹、建包利于程序的管理和维护。
-
建包的语法格式:package 公司域名倒写.技术名称。报名建议全部英文小写,且具备意义
package com.xxx.javabean; public class ...
-
建包语句必须在第一行,一般IDEA工具会帮助创建
导包:
- 相同包下的类可以直接访问,不同包下的类必须导包,才可以使用!
导包格式:import 包名.类名; - 假如一个类中需要用到不同类,而这个两个类的名称是一样的,那么默认只能导入一个类,另一个类要带包名访问。
权限修饰符
- 权限修饰符:是用来控制一个成员能够被访问的范围。
- 可以修饰成员变量,方法,构造器,内部类。
权限修饰符:有四种作用范围由小到大(private -> 缺省 -> protected - > public )
修饰符 | 同一个类中 | 同一个包中其他类 | 不同包下的子类 | 不同包下的无关类 |
---|---|---|---|---|
private | √ | |||
缺省 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
final
final关键字是最终的意思,可以修饰(类、方法、变量)
- 修饰类:表明该类是最终类,不能被继承。
- 修饰方法:表明该方法是最终方法,不能被重写。
- 修饰变量:表示该变量第一次赋值后,不能再次被赋值(有且仅能被赋值一次)。
- 修饰基本类型:那么变量存储的数据值不能发生改变。
- 修饰引用类型:那么变量存储的地址值不能发生改变,但是地址指向的对象内容是可以发生变化的。
常量
使用了public static final
修饰的成员变量,必须有初始化值,而且执行的过程中其值不能被改变。
- 命名规范:英文单词全部大写,多个单词下划线连接起来
- 作用:通常用来记录系统的配置数据。好处:
- 在编译阶段会进行“宏替换”:把使用常量的地方全部替换成真实的字面量。
- 维护系统容易,可读性更好。
public class Constant {
public static final String SCHOOL_NAME = “中国大学";
public static final String LOGIN_NAME = “admin";
public static final String PASS_WORD = “123456";
}
枚举
Java中的一种特殊类型,是为了做信息的标志和信息的分类。
// 定义格式
修饰符 enum 枚举名称{
第一行都是罗列枚举类实例的名称。
}
// 例:
enum Season{
SPRING , SUMMER , AUTUMN , WINTER;
}
// 使用javap命令反编译后得到:
Compiled from "Season.java"
public final class Season extends java.lang.Enum<Season> {
public static final Season SPRING = new Season();
public static final Season SUMMER = new Season();
public static final Season AUTUMN = new Season();
public static final Season WINTER = new Season();
public static Season[] values();
public static Season valueOf(java.lang.String);
}
根据反编译结果可以得到枚举的特征:
- 枚举类都是继承了枚举类型:java.lang.Enum
- 枚举都是最终类,不可以被继承。
- 构造器都是私有的,枚举对外不能创建对象。
- 枚举类的第一行默认都是罗列枚举对象的名称的。
- 枚举类相当于是多例模式。
抽象类
在Java中abstract是抽象的意思,可以修饰类、成员方法。
// 定义格式
修饰符 abstract class 类名{
修饰符 abstract 返回值类型 方法名称(形参列表);
}
注意:
- 抽象方法只有方法签名,不能声明方法体。
- 一个类中如果定义了抽象方法,这个类必须声明成抽象类,否则报错。
使用场景:
- 抽象类可以理解成不完整的设计图,一般作为父类,让子类来继承。
- 当父类知道子类一定要完成某些行为,但是每个子类对该行为的实现又不同,于是父类就把该行为定义成抽象方法,具体实现交给子类去完成。
特征:
- 普通类有的成员(成员变量、方法、构造器),抽象类都具备
- 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
- 一个类继承了抽象类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。
- 不能用abstract修饰变量、代码块、构造器。
- 最重要的特征:得到了抽象方法,失去了创建对象的能力
与final的互斥关系:
- abstract定义的抽象类作为模板让子类继承,final定义的类不能被继承。
- 抽象方法定义通用功能让子类重写,final定义的方法子类不能重写。
多态
概述
指对象可以有多种形态,常见定义形式:
父类类型 对象名称 = new 子类构造器;
成员访问特点:
- 方法调用:编译看左边,运行看右边。
- 变量调用:编译看左边,运行也看左边。
优点:
- 在多态形式下,右边对象可以实现解耦合,便于扩展和维护。
- 定义方法的时候,使用父类型作为参数,该方法就可以接收这父类的一切子类对象,体现出多态的扩展性与便利。
缺点:
- 多态下不能使用子类的独有功能
类型转换
从子到父:自动类型转换;
从父到子:强制类型转换;必须强制转换,否则报错: 子类 对象变量 = (子类)父类类型的变量
-
作用:可以解决多态下的劣势,可以实现调用子类独有的功能。
-
注意:有继承/实现关系的类就可以在编译阶段进行强制类型转换;但是,如果转型后的类型和对象真实对象的类型不是同一种类型,那么在运行代码时,就会出现ClassCastException。
建议强转转换前使用instanceof判断当前对象的真实类型,再进行强制转换。语法:变量名 instanceof 真实类型
说明:判断关键字左边的变量指向的对象的真实类型,是否是右边的类型或者是其子类类型,是则返回true,反之false。
接口
概述
接口定义格式如下:
public interface 接口名 {
// 常量
// 抽象方法
}
- JDK8之前接口中只能是抽象方法和常量,没有其他成分了。
- 接口不能实例化。
- 接口中的成员都是public修饰的,写不写都是,因为规范的目的是为了公开化。
用法
接口是用来被类实现(implements)的,实现接口的类称为实现类。实现类可以理解成所谓的子类。
修饰符 class 实现类 implements 接口1, 接口2, 接口3 , ... {
}
从上面可以看出,接口可以被类单实现,也可以被类多实现。
注意:
- 一个类实现接口,必须重写完全部接口的全部抽象方法,否则这个类需要定义成抽象类。
继承
-
类和类的关系:单继承。
-
类和接口的关系:多实现。
-
接口和接口的关系:多继承,一个接口可以同时继承多个接口。
多继承的好处:规范合并,整合多个接口为同一个接口,便于子类实现。
JDK8开始新增的方法
-
默认方法:类似之前写的普通实例方法:必须用default修饰。
默认会public修饰。需要用接口的实现类的对象来调用
default void run(){ ... }
-
静态方法:默认会public修饰,必须static修饰。
接口的静态方法必须用接口名来调用。
static void inAddr(){ ... }
-
私有方法:使用private修饰,从JDK 1.9才开始有的。
只能在本类中被其他的默认方法或者私有方法访问。
private void go(){ System.out.println("--准备--"); }
增加上述方法的原因:
接口一旦增减方法或成员后,所有实现类都需要修改,改动成本高。
了解即可,多是Java源码使用。
注意事项
- 接口不能创建对象
- 一个类实现多个接口,多个接口的规范不能冲突
- 一个类实现多个接口,多个接口中有同样的静态方法不冲突。
- 一个类继承了父类,同时又实现了接口,父类中和接口中有同名方法,默认用父类的。
- 一个类实现了多个接口,多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。
- 一个接口继承多个接口,是没有问题的,如果多个接口中存在规范冲突则不能多继承。例如存在同名、同参的方法,返回类型却不同。
内部类
内部类就是定义在一个类里面的类,里面的类可以理解成(寄生),外部类可以理解成(宿主)。
public class People{
// 内部类
public class Heart{
}
}
使用场景:当一个事物的内部,还有一个部分需要一个完整的结构进行描述时。
作用:
-
内部类通常可以方便访问外部类的成员,包括私有的成员。
-
内部类提供了更好的封装性,本身就可以用private ,protectecd等修饰,封装性可以做更多控制。
静态内部类(了解)
public class Outer{
// 静态成员内部类
public static class Inner{
}
}
有static修饰,属于外部类本身。
它的特点和使用与普通类是完全一样的,类有的成分它都有,只是位置在别人里面而已。
创建对象格式:外部类名.内部类名 对象名 = new 外部类名.内部类构造器,例:
Outer.Inner in = new Outer.Inner()
成员内部类(了解)
无static修饰,属于外部类的对象。
JDK16之前,成员内部类中不能定义静态成员,JDK 16开始也可以定义静态成员了。
public class Outer {
// 成员内部类
public class Inner {
}
}
创建格式:外部类名.内部类名 对象名 = new 外部类构造器.new 内部类构造器();
范例:Outer.Inner in = new Outer().new Inner();
若内部类与外部类有同名变量,需要访问外部类变量时,使用 外部类.this.<变量名>
局部内部类(了解)
局部内部类放在方法、代码块、构造器等执行体中。
局部内部类的类文件名为: 外部类$N内部类.class(N为流水,防止有同名内部类)
鸡肋语法,了解即可
匿名内部类
本质上是一个没有名字的局部内部类。
作用:方便创建子类对象,最终目的是为了简化代码编写
// 定义格式
new 类|抽象类名|或者接口名() {
重写方法;
};
// 例
Employee a = new Employee() {
public void work() {
}
};
a. work();
特点:
-
匿名内部类是一个没有名字的内部类,同时也代表一个对象。
-
匿名内部类产生的对象类型,相当于是当前new的那个的类型的子类类型。
-
匿名内部类可以作为一个对象,直接传输给方法。
// 为按钮绑定点击事件监听器。 btn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println("登录一下~~"); } }); // 简化 // btn.addActionListener(e -> System.out.println("登录一下~~"));
包装类
8种基本数据类型对应的引用类型:
基本数据类型 | 引用数据类型 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
char | Character |
float | Float |
double | Double |
boolean | Boolean |
Java为了实现一切皆对象,为8种基本类型提供了对应的引用类型。
常用的集合和泛型其实也只能支持包装类型,不支持基本数据类型
自动装箱:基本类型的数据和变量可以直接赋值给包装类型的变量
自动拆箱:包装类型的变量可以直接赋值给基本数据类型的变量。
好处:
-
包装类的变量的默认值可以是null,容错率更高。
-
可以把基本类型的数据转换成字符串类型(用处不大)
调用toString()方法得到字符串结果。
调用Integer.toString(基本类型的数据)。
-
可以把字符串类型的数值转换成真实的数据类型(真的很有用)
Integer.parseInt(“字符串类型的整数”)
Double.parseDouble(“字符串类型的小数”)
正则表达式
正则表达式可以用一些规定的字符来制定规则,并用来校验数据格式的合法性,如校验QQ号为6~11位的纯数字。
字符串
字符串对象提供了匹配正则表达式的方法:
// 判断是否匹配正则表达式,匹配返回true,不匹配返回false。
public boolean matches(String regex)
字符类表达式(默认匹配一个字符)
[abc] | 只能是a, b, 或c |
---|---|
[^abc] | 除了a, b, c之外的任何字符 |
[a-zA-Z] | a到z A到Z,包括(范围) |
[a-d[m-p]] | a到d,或m通过p:([a-dm-p]联合) |
[a-z&&[def]] | d, e, 或f(交集) |
[a-z&&[^bc]] | a到z,除了b和c:([ad-z]减法) |
[a-z&&[^m-p]] | a到z,除了m到p:([a-lq-z]减法) |
预定义的字符类(默认匹配一个字符)
. | 任何字符 |
---|---|
\d | 一个数字: [0-9] |
\D | 非数字: [^0-9] |
\s | 一个空白字符: [ \t\n\x0B\f\r] |
\S | 非空白字符: [^\s] |
\w | [a-zA-Z_0-9] 英文、数字、下划线 |
\W | [^\w] 一个非单词字符 |
贪婪的量词(配合匹配多个字符)
X? | X , 一次或根本不 |
---|---|
X* | X,零次或多次 |
X+ | X , 一次或多次 |
X | X,正好n次 |
X | X,至少n次 |
X | X,至少n但不超过m次 |
示例:
System.out.println("a".matches("[abc]")); // true
System.out.println("z".matches("[abc]")); // false
System.out.println("ab".matches("[abc]")); // false
System.out.println("ab".matches("[abc]+")); //true
应用:
方法名 | 说明 |
---|---|
public String replaceAll(String regex,String newStr) | 按照正则表达式匹配的内容进行替换 |
public String[] split(String regex) | 按照正则表达式匹配的内容进行分割字符串,反回一个字符串数组。 |
标准类
通过Pattern+Matcher获取匹配的值,示例:
String rs = "学习Java,电话020-43422424,或者联系邮箱" +
"itcast@itcast.cn,电话18762832633,0203232323" +
"邮箱bozai@itcast.cn,400-100-3233 ,4001003232";
// 需求:从上面的内容中爬取出 电话号码和邮箱。
// 1.定义爬取规则
String regex = "(\\w{1,}@\\w{2,10}(\\.\\w{2,10}){1,2})|" +
"(1[3-9]\\d{9})|(0\\d{2,5}-?\\d{5,15})|400-?\\d{3,8}-?\\d{3,8}";
// 2.编译正则表达式成为一个匹配规则对象
Pattern pattern = Pattern.compile(regex);
// 3.通过匹配规则对象得到一个匹配数据内容的匹配器对象
Matcher matcher = pattern.matcher(rs);
// 4.通过匹配器去内容中爬取出信息
while(matcher.find()){
System.out.println(matcher.group());
}
常见算法
- 冒泡排序
void bubbleSort(Integer[] integers) {
Integer tmp;
for (int i = 0; i < integers.length - 1; i++) {
for (int j = i + 1; j < integers.length; j++) {
if (integers[i] > integers[j]) {
tmp = integers[i];
integers[i] = integers[j];
integers[j] = tmp;
}
}
}
System.out.println(Arrays.toString(integers));
}
- 选择排序法
static void selectSort(Integer[] integers) {
Integer tmp;
int index;
for (int i = 0; i < integers.length - 1; i++) {
index = i;
for (int j = i + 1; j < integers.length; j++) {
if (integers[j] < integers[index]) {
index = j;
}
}
if (index != i) {
tmp = integers[i];
integers[i] = integers[index];
integers[index] = tmp;
}
}
System.out.println(Arrays.toString(integers));
}
- 二分查找
static int binarySearch(Integer[] integers, Integer target) {
int index = -1;
int middleIndex, beginIndex = 0, endIndex = integers.length - 1;
while (beginIndex <= endIndex) {
middleIndex = (beginIndex + endIndex) / 2;
if (integers[middleIndex] < target) beginIndex = middleIndex + 1;
else if (integers[middleIndex] > target) endIndex = middleIndex - 1;
else return middleIndex;
}
return index;
}
Lambda
Lambda表达式是JDK 8开始后的一种新语法形式,用于简化匿名内部类的代码写法:
(匿名内部类被重写方法的形参列表) -> {
被重写方法的方法体代码。
}
注:-> 是语法形式,无实际含义
注意:Lambda表达式只能简化函数式接口的匿名内部类的写法形式。
函数式接口:接口;有且仅有一个抽象方法
省略写法(进一步在Lambda表达式的基础上继续简化):
-
参数类型可以省略不写。
-
如果只有一个参数,参数类型可以省略,同时参数外层的()也可以省略。
-
如果Lambda表达式的方法体代码只有一行代码,可以省略大括号不写,同时要省略分号!
-
如果Lambda表达式的方法体代码只有一行代码,可以省略大括号不写。此时,如果这行代码是return语句,必须省略return不写,同时也必须省略";"不写
泛型
JDK5中引入的特性,可以在编译阶段约束操作的数据类型,并进行检查。
格式:<数据类型>; 注意:泛型只支持引用数据类型。
好处:
- 统一数据类型。
- 把运行时期的问题提前到了编译期间,避免了强制类型转换可能出现的异常。
可使用的地方:
-
类后面
-
方法申明上
-
接口后面
通配符"?":可以在使用泛型的时候代表一切类型,有2种:
- ? extends Car: ?必须是Car或者其子类,泛型上限
- ? super Car : ?必须是Car或者其父类,泛型下限
集合体系的全部接口和实现类都是支持泛型的使用的
可变参数
用在形参中来接收多个数据。
格式:数据类型...参数名称。
作用:接收参数非常灵活,方便。可以不接收参数,可以接收1个或者多个参数,也可以接收一个数组。在方法内部本质上就是一个数组
注意:
- 一个形参列表中可变参数只能有一个
- 可变参数必须放在形参列表的最后面
异常
概述
异常是程序在“编译”或者“执行”的过程中可能出现的问题(语法错误不算在异常体系中),如数组索引越界、空指针异常、 日期格式化异常。
异常一旦出现了,如果没有提前处理,程序就会退出JVM虚拟机而终止.
研究异常并且避免异常,然后提前处理异常,保证程序的安全、 健壮性。
异常体系:
Error:系统级别问题、JVM退出等,代码无法控制。
Exception:java.lang包下,称为异常类,它表示程序本身可以处理的问题。
- RuntimeException及其子类:运行时异常,编译阶段不会报错。一般是程序员业务没有考虑好或者是编程逻辑不严谨引起的程序错误。示例:
- 数组索引越界异常: ArrayIndexOutOfBoundsException
- 空指针异常 : NullPointerException,直接输出没有问题,但是调用空指针的变量的功能就会报错。
- 数学操作异常:ArithmeticException
- 类型转换异常:ClassCastException
- 数字转换异常: NumberFormatException
- 除RuntimeException之外所有的异常:编译时异常,编译期必须处理的,否则程序不能通过编译。 (日期格式化异常等)。
处理流程
-
默认处理
- 在出现异常的代码那里自动创建一个异常对象。
- 异常会从方法中出现的点这里抛出给调用者,调用者最终抛出给JVM虚拟机。
- 虚拟机接收到异常对象后,先在控制台直接输出异常栈信息数据。
- 直接从当前执行的异常点干掉当前程序。
后续代码没有机会执行了,因为程序已经死亡。
-
手动处理方式
- 出现异常直接抛出去给调用者,调用者也继续抛出去。
方法 throws 异常1 ,异常2 ,异常3 ..{ }
- 出现异常自己捕获处理,不麻烦别人。
try{ // 监视可能出现异常的代码! }catch(异常类型1 变量){ // 处理异常 }catch(异常类型2 变量){ // 处理异常 }...
- 前两者结合,出现异常直接抛出去给调用者,调用者捕获处理。
自定义异常
Java无法为这个世界上全部的问题提供异常类。
如果企业想通过异常的方式来管理自己的某个业务问题,就需要自定义异常类了。
自定义编译时异常
- 定义一个异常类继承Exception.
- 重写构造器。
- 在出现异常的地方用throw new 自定义对象抛出,
作用:编译时异常是编译阶段就报错,提醒更加强烈,一定需要处理!!
自定义运行时异常
- 定义一个异常类继承RuntimeException.
- 重写构造器。
- 在出现异常的地方用throw new 自定义对象抛出!
作用:提醒不强烈,编译阶段不报错!!运行时才可能出现!!
字符集
字符集(Character Set)是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集有:
-
ASCII字符集:
(American Standard Code for Information Interchange,美国信息交换标准代码):包括了数字、英文、符号。
使用1个字节存储一个字符,一个字节是8位,总共可以表示128个字符信息,对于表示英文、数字来说是够用
-
GBK字符集
包含了几万个汉字等字符,同时也要兼容ASCII编码,
GBK编码中一个中文字符一般以两个字节的形式存储。
-
Unicode(UTF-8)字符集
统一码,也叫万国码,是计算机科学领域里的一项业界标准。
UTF-8是Unicode的一种常见的可变长度编码方式。
UTF-8编码后一个中文以三个字节的形式存储,同时也要兼容ASCII编码表。
英文和数字在任何国家的编码中都不会乱码
编码
方法名称 | 说明 |
---|---|
byte[] getBytes() | 使用平台的默认字符集将该 String编码为一系列字节,将结果存储到新的字节数组中 |
byte[] getBytes(String charsetName) | 使用指定的字符集将该 String编码为一系列字节,将结果存储到新的字节数组中 |
解码
构造器 | 说明 |
---|---|
String(byte[] bytes) | 通过使用平台的默认字符集解码指定的字节数组来构造新的 String |
String(byte[] bytes, String charsetName) | 通过指定的字符集解码指定的字节数组来构造新的 String |