一、面向对象编程
Java是一种面向对象的编程语言。面向对象编程,英文是Object-Oriented Programming,简称OOP。是一种通过对象的方式,把现实世界映射到计算机模型的一种编程方法。
二、继承
(一)方法的重写
@Override不是必需的。加上@Override可以让编译器帮助检查是否进行了正确的重写。希望进行重写,但是不小心写错了方法签名,编译器会报错。
(二)向上转型和向下转型
向上转型(多态):父类引用指向子类对象。Java的实例方法调用是基于运行时的实际类型的动态调用,而非变量的声明类型。
向下转型:把父类类型转为子类类型,可以强制向下转型,最好借助instanceof判断。向下转型很可能会失败。失败的时候,Java虚拟机会报ClassCastException。instanceof实际上判断一个变量所指向的实例是否是指定类型,或者这个类型的子类。如果一个引用变量为null,那么对任何instanceof的判断都为false。
Student n = null; System.out.println(n instanceof Student); // false
Person p = new Student();
if (p instanceof Student) {
// 只有判断成功才会向下转型:
Student s = (Student) p; // 一定会成功
}
从Java 14开始,判断instanceof后,可以直接转型为指定变量,避免再次强制转型。
Object obj = "hello";
if (obj instanceof String s) {
// 可以直接使用变量s:
System.out.println(s.toUpperCase());
}
三、多态(Polymorphic)
(一)前提:
1.继承
2.父类引用指向子类对象
3.方法的重写
(二)多态是指,针对某个类型的方法调用,其真正执行的方法取决于运行时期实际类型的方法。
多态的特性就是,运行期才能动态决定调用的子类方法。对某个类型调用某个方法,执行的实际方法可能是某个子类的覆写方法。
多态具有一个非常强大的功能,就是允许添加更多类型的子类实现功能扩展,却不需要修改基于父类的代码。
四、final修饰符作用
final修饰的方法可以阻止被覆写;
final修饰的class可以阻止被继承;
final修饰的field必须在创建对象时初始化,随后不可修改。
五、接口与抽象类
| 对比 | abstract class | interface |
|---|---|---|
| 继承 | 只能extends一个class | 可以implements多个interface |
| 字段 | 可以定义实例字段 | 默认是public static final类型 |
| 抽象方法 | 存在抽象方法 | 默认都是public abstract类型 |
| 非抽象方法 | 可以定义非抽象方法 | 可以定义default方法(JDK>=1.8), |
默认方法(default方法):
实现类可以不必覆写default方法。default方法的目的是,当我们需要给接口新增一个方法时,会涉及到修改全部子类。如果新增的是default方法,那么子类就不必全部修改,只需要在需要覆写的地方去覆写新增方法。
default方法和抽象类的普通方法是有所不同的。因为interface没有字段,default方法无法访问字段,而抽象类的普通方法可以访问实例字段。
六、static
静态字段属于所有实例“共享”的字段,实际上是属于class的字段;
调用静态方法不需要实例,无法访问this,但可以访问静态字段和其他静态方法;
静态方法常用于工具类和辅助方法。
七、内部类
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访问权限。
Outer类被编译为Outer.class,而Inner类被编译为Outer$Inner.class,匿名类被编译为Outer$1.class,如果有多个匿名类,Java编译器会将每个匿名类依次命名为Outer$1、Outer$2、Outer$3。
八、classpath
(一)作用:JVM通过classpath决定搜索class的路径和顺序。
假设classpath是.;C:workproject1bin;C:shared,当JVM在加载abc.xyz.Hello这个类时,会依次查找:
<当前目录>abcxyzHello.class
C:workproject1binabcxyzHello.class
C:sharedabcxyzHello.class
注意到.代表当前目录。如果JVM在某个路径下找到了对应的class文件,就不再往后继续搜索。如果所有路径下都没有找到,就报错。
(二)默认classpath
JVM默认的classpath为.,即当前目录。
在IDE中运行Java程序,IDE自动传入的-cp参数是当前工程的bin目录和引入的jar包。
(三)设置classpath
不推荐设置系统环境变量classpath,始终建议在启动JVM时,通过-cp(或-classpath)命令传入;
java -cp .;C:workproject1bin;C:shared abc.xyz.Hello
(四)jar包
jar包实际上就是一个zip格式的压缩文件,而jar包相当于目录。如果我们要执行一个jar包的class,就可以把jar包放到classpath中:
java -cp ./hello.jar abc.xyz.Hello
注意:JVM自带的标准库rt.jar不要写到classpath中,写了反而会干扰JVM的正常运行。
Java社区提供了大量的开源构建工具,例如Maven,可以非常方便地创建jar包。
(五)模块
Java 9引入的模块目的是为了管理依赖;
使用模块可以按需打包JRE;
使用模块对类的访问权限有了进一步限制。
九、Java核心类
(一)String
1)String是不可变对象。这种不可变性是通过内部的private final char[]字段,以及没有任何修改char[]的方法实现的。
2)Java编译器在编译期,会自动把所有相同的字符串当作一个对象放入常量池。
3)String还提供了isEmpty()和isBlank()来判断字符串是否为空和空白字符串:
"".isEmpty(); // true,因为字符串长度为0 " ".isEmpty(); // false,因为字符串长度不为0 " n".isBlank(); // true,因为只包含空白字符 " Hello ".isBlank(); // false,因为包含非空白字符
4)拼接字符串
拼接字符串使用静态方法join(),它用指定的字符串连接字符串数组:
String[] arr = {"A", "B", "C"};
String s = String.join("***", arr); // "A***B***C"
5)格式化字符串
字符串提供了formatted()方法和format()静态方法,可以传入其他参数,替换占位符,然后生成新的字符串
String s = "Hi %s, your score is %d!";
System.out.println(s.formatted("Alice", 80));
System.out.println(String.format("Hi %s, your score is %.2f!", "Bob", 59.5));
(二)StringBuilder
StringBuilder,它是一个可变对象,用来高效拼接字符串,可以预分配缓冲区,这样,往StringBuilder中新增字符时,不会创建新的临时对象
StringBuilder还可以进行链式操作。如果我们查看StringBuilder的源码,可以发现,进行链式操作的关键是,定义的append()方法会返回this(实例本身),这样,就可以不断调用自身的其他方法。仿照StringBuilder,我们也可以设计支持链式操作的类。
StringBuffer是Java早期的一个StringBuilder的线程安全版本,它通过同步来保证多个线程操作StringBuffer也是安全的,但是同步会带来执行速度的下降。StringBuilder和StringBuffer接口完全相同,现在完全没有必要使用StringBuffer。



