目录
面向对象编程
面向对象基础
1.方法
命令行参数类型是String[]数组;
命令行参数由JVM接收用户输入并传给main方法;
如何解析命令行参数需要由程序自己实现。
2.构造方法
实例在创建时通过new操作符会调用其对应的构造方法,构造方法用于初始化实例;
没有定义构造方法时,编译器会自动创建一个默认的无参数构造方法;
可以定义多个构造方法,编译器根据参数自动判断;
可以在一个构造方法内部调用另一个构造方法,便于代码复用。
3.抽象类
- 通过abstract定义的方法是抽象方法,它只有定义,没有实现。抽象方法定义了子类必须实现的接口规范;
- 定义了抽象方法的class必须被定义为抽象类,从抽象类继承的子类必须实现抽象方法;
- 如果不实现抽象方法,则该子类仍是一个抽象类;
- 面向抽象编程使得调用者只关心抽象方法的定义,不关心子类的具体实现。
4.接口
Java的接口(interface)定义了纯抽象规范,一个类可以实现多个接口;
接口也是数据类型,适用于向上转型和向下转型;
接口的所有方法都是抽象方法,接口不能定义实例字段;
接口可以定义default方法(JDK>=1.8)。
5.静态字段和静态方法
- 静态字段属于所有实例“共享”的字段,实际上是属于class的字段;
- 调用静态方法不需要实例,无法访问this,但可以访问静态字段和其他静态方法;
- 静态方法常用于工具类和辅助方法。
Java内建的package机制是为了避免class命名冲突;
JDK的核心类使用java.lang包,编译器会自动导入;
JDK的其它常用类定义在jav包
Java内建的package机制是为了避免class命名冲突;
JDK的核心类使用java.lang包,编译器会自动导入;
JDK的其它常用类定义在java.util.*,java.math.*,java.text.*,……;
包名推荐使用倒置的域名,例如org.apache
a.util.*,java.math.*,java.text.*,……;
6.包
Java内建的package机制是为了避免class命名冲突;
JDK的核心类使用java.lang包,编译器会自动导入;
JDK的其它常用类定义在java.util.*,java.math.*,java.text.*,……;
包名推荐使用倒置的域名,例如org.apache
名推荐使用倒置的域名,例如org.apache
7.作用域
Java内建的访问权限包括public、protected、private和package权限;
- private:私有访问修饰符,只能在声明它的类内部访问。无论是否在同一包内,都无法在其他类中直接访问。
- default(默认):默认访问修饰符。如果没有明确指定访问修饰符,即没有使用任何访问修饰符关键字,将被视为默认访问修饰符。默认修饰符允许在同一包内访问,但在其他包中无法直接访问。
- protected:受保护的访问修饰符。在同一包内,以及不同包中的子类中无论是否在同一包内),都可以访问受保护的成员。但是,非子类不在同一包内其他类无法直接访问。
- public:公共访问修饰符。公共成员可以在任何位置都可见和访问,无论是否在同一包内。
Java在方法内部定义的变量是局部变量,局部变量的作用域从变量声明开始,到一个块结束;
final修饰符不是访问权限,它可以修饰class、field和method;
一个.java文件只能包含一个public类,但可以包含多个非public类。
8.内部类
Java的内部类可分为Inner Class、Anonymous Class和Static Nested Class三种:
- Inner Class和Anonymous Class本质上是相同的,都必须依附于Outer Class的实例,即隐含地持有Outer.this实例,并拥有Outer Class的private访问权限;
- Static Nested Class是独立类,但拥有Outer Class的private访问权限。
9.classpath和jar
JVM通过环境变量classpath决定搜索class的路径和顺序;
不推荐设置系统环境变量classpath,始终建议通过-cp命令传入;
jar包相当于目录,可以包含很多.class文件,方便下载和使用;
- MF文件可以提供jar包的信息,如Main-Class,这样可以直接运行jar包。
10.class版本
java.lang.UnsupportedClassVersionError: Xxx has been compiled by a more recent version of the Java Runtime...
只要看到UnsupportedClassVersionError就表示当前要加载的class文件版本超过了JVM的能力,必须使用更高版本的JVM才能运行。
指定编译输出有两种方式,一种是在javac命令行中用参数--release设置:
$ javac --release 11 Main.java
参数--release 11表示源码兼容Java 11,编译的class输出版本为Java 11兼容,即class版本55。
小结
高版本的JDK可编译输出低版本兼容的class文件,但需注意,低版本的JDK可能不存在高版本JDK添加的类和方法,导致运行时报错。
运行时使用哪个JDK版本,编译时就尽量使用同一版本编译源码。
11.模块
Java 9引入的模块目的是为了管理依赖;
使用模块可以按需打包JRE;
使用模块对类的访问权限有了进一步限制。
class文件是跨平台的,Java虚拟机不是。
java核心类
1.字符串和编码
- Java字符串String是不可变对象;
- 字符串操作不改变原字符串内容,而是返回新字符串;
- 常用的字符串操作:提取子串、查找、替换、大小写转换等;
- Java使用Unicode编码表示String和char;
- 转换编码就是将String和byte[]转换,需要指定编码;
- 转换为byte[]时,始终优先考虑UTF-8编码。
2.StringBuilder
StringBuilder是可变对象,用来高效拼接字符串;
StringBuilder可以支持链式操作,实现链式操作的关键是返回实例本身;
StringBuffer是StringBuilder的线程安全版本,现在很少使用。
3.StringJoiner
用指定分隔符拼接字符串数组时,使用StringJoiner或者String.join()更方便;
用StringJoiner拼接字符串时,还可以额外附加一个“开头”和“结尾”。
4.包装类型
Java核心库提供的包装类型可以把基本类型包装为class;
自动装箱和自动拆箱都是在编译期完成的(JDK>=1.5);
装箱和拆箱会影响执行效率,且拆箱时可能发生NullPointerException;
包装类型的比较必须使用equals();
整数和浮点数的包装类型都继承自Number;
包装类型提供了大量实用方法。
5.JavaBean
JavaBean是一种符合命名规范的class,它通过getter和setter来定义属性;
属性是一种通用的叫法,并非Java语法规定;
可以利用IDE快速生成getter和setter;
使用Introspector.getBeanInfo()可以获取属性列表。
6.enum枚举
Java使用enum定义枚举类型,它被编译器编译为final class Xxx extends Enum { … };
通过name()获取常量定义的字符串,注意不要使用toString();
通过ordinal()返回常量定义的顺序(无实质意义);
可以为enum编写构造方法、字段和方法
enum的构造方法要声明为private,字段强烈建议声明为final;
enum适合用在switch语句中。
7.纪录类
从Java 14开始,提供新的record关键字,可以非常方便地定义Data Class:
- 使用record定义的是不变类;
- 可以编写Compact Constructor对参数进行验证;
- 可以定义静态方法。
8.BigInteger
BigInteger用于表示任意大小的整数;
BigInteger是不变类,并且继承自Number;
将BigInteger转换成基本类型时可使用longValueExact()等方法保证结果准确。
9.BigDecimal
BigDecimal用于表示精确的小数,常用于财务计算;
比较BigDecimal的值是否相等,必须使用compareTo()而不能使用equals()。