设计目标:Java~采用面向对象的方式,开发健壮的代码,花费最少的时间和减少困难

基本要素

1.Java语言特点

面向对象:分析事物,将其抽象为一类包含相同特性(属性)、行为(功能)的对象集合。
编译&解释共存:Java源程序先被编译为字节码,再由JVM虚拟机将字节码解释成机器码。
平台无关性:Java程序由Java虚拟机实现其平台无关性。
多线程、稳健、安全可靠……

2.三大构件

JDK:Java开发环境,提供了Java工具和基本Java类库
JRE:Java运行环境,包含JVM标准实现和Java核心类库
JVM:Java虚拟机,用于解释字节码文件

语法基础

1.基本语法

变量、常量、标识符、关键字、运算符、流程控制

2.基本类型&包装类型

基本数据类型

数据类型 字节 位数
byte(字节) 1 8
short(短整型) 2 16
int(整形) 4 32
long(长整形) 8 64
char(字符型) 2 16
float(单精度浮点型) 4 32
double(双精度浮点型) 8 64
boolean(布尔型)
1

包装类型
包装类型是将基本数据类型转化为引用类型(对象实例)。
类型:Byte、Short、Integer、Long、Float、Double、Character、Boolean
包装类型缓存机制
Byte、Short、Integer、Long这4中类型都创建了[-128, 127]数值缓存;
Character创建了[0, 127]数值缓存;
Boolean提供了True、False。
注:当基本类型转化为引用类型后,如何超出数值范围,则需要创建新的对象。
基本类型&包装类型区别
初始化:基本类型初始化默认值不为null、包装类型不赋值则初始化为null
空间存储:包装类型属于对象,存在于堆内存中;未被static修饰的成员变量基本类型存在于堆中。
空间占用:基本类型占用空间小
泛型适用:包装类型可以用于泛型
自动装箱&拆箱
自动装箱:将基本类型包装成引用类型;
自动拆箱:将包装的引用类型拆解成基本类型;

  1. Integer i = 10; // 装箱
  2. int n = i; // 拆箱

3.类的访问修饰符

修饰符 当前类 同包 子类 其他包
public Y Y Y Y
protected Y Y Y
default Y Y
private Y

面向对象

1.类

类:包含一类对象的特性、行为,是对象的蓝图。类是一种数据类型。只存在于.class文件中。
成员变量&局部变量:
语法形式:
成员变量存在于类中。局部变量存在于代码块、方法中。
局部变量只能被final修饰。成员变量修饰范围更广泛。
存储方式:
成员变量被static修饰,则属于类。未被static修饰,则属于对象,存储于堆内存中。
局部变量存储于栈内存中。
生命周期:
成员变量属于对象,生命周期和对象一致。
局部变量存在于方法栈中,生命周期和方法一致。
初始值:
成员变量不赋值时,则通常采用各自的默认值初始化。如果被final修饰,则必须显示初始化赋值。
局部变量则不会自动赋值。

2.构造器

Java中类的构造器主要用于确保类在调用之前能够初始化,提高了Java编程中的安全性。

3.方法重载&方法重写

方法重载:方法重载作用于同类中,只与方法中的参数个数、类型、顺序有关,与其他无关。构造器是一种特殊的方法重载。方法重载使用Overload修饰。
方法重写:方法重写作用于父子继承关系中,通常用于子类对父类已有的方法进行自身的改造。方法重写使用Override修饰

4.this&static&final

this:代表调用者对象自身,通常存储与堆内存中的对象中,是一个对自身的引用。
static:用于区分成员是属于类,还是属于对象实例。编译期直接进行内存的初始化分配,且只占用一份存储空间。对于一些没有必要初始化的类、特性、行为等,则推荐使用static关键字来进行标识。
final:标识于类、属性、方法。常量、且不可继承。private方法中隐式的指定为final。

5.三大特征

封装:隐藏具体的实现细节,只对外提供可访问的接口。安全性。
注意点:
1.Java中单继承,且所有类都间接的继承自Object类。
2.private方法中通常隐式的指定了final。
3.子类可以拥有基类的特性、行为;基类中的私有方法只能拥有,无法访问。构造器无法继承,通过supper()调用基类构造。
4.子类构造初始化之前,会先初始化基类的构造器。
继承:抽离出多个类中共享的特性、行为来构造成一个共用的父类。复用性。
多态:同一类对象的多种实现方式。
子类赋值给父类引用时,则发生向上转型;将父类强制转换为子类对象,则发生向下转型。
静态方法、构造器不存在多态(构造器中隐式的声明了static,子类初始化调用时,则会首先向上链接初始化加载父类构造)。

6.接口

1.抽象类&抽象方法
界定:包含抽象方法的类叫做抽象类,用abstract修饰。(包含抽象方法时,必须声明为抽象类,否则编译报错)。抽象类是介于接口和子类之间的一个非完全抽象类
抽象方法:方法声明是一样的,但是不同的子类中具有不同的实现。
注意点:
抽象类中可以包含非抽象方法(提供方法实现),当所有子类都需要实现相同的方法,且方法体一样;并且还可实现自己特有的方法时,推荐使用abstract父类进行抽象。
将都需要实现的fly()方法定义为非抽象方法并进行实现;
将eat()方法定义为abstract抽象的,让其子类自己实现。
2.接口
界定:接口是一种完全抽象的抽象类,其中的方法均为抽象声明,不提供具体的实现。用interface修饰。
接口域:接口中的域都是static、final的。且必须进行一个初始化,不能存在空的final。

7.抽象类&接口差异

相同点:
都无法直接实例化;
都包含抽象方法;
都提供了默认方法实现。
不同点:
接口是完全抽象的,重在提倡类的行为约束;抽象类是一种非完全抽象的,重在提倡代码的复用性。
接口中的域均为public static final,且必须初始化赋值;抽象类中的域为default、不必初始化赋值,子类可重新定义与赋值。

8.内部类

界定:定义在类中的类叫做“内部类”。
作用:将类的实现隐藏到所需的类中,是一种关联组织,并不等同于组合。了解外围类,并可与之通信。
类型:成员内部类(类中的成员变量)、 局部内部类(方法中定义)、静态内部类(static修饰,与外围类无 联系)、匿名内部类(定义内部类的同时提供类的实现)。
语法;

  1. //常见用法
  2. public class User{
  3. //
  4. class avator{
  5. //内部类中的方法可以访问外部类的字段
  6. }
  7. }

访问:内部类访问外围类,使用外围类.this。外围类创建内部类,使用外围类.new 内部类();

  1. //.this使用实例
  2. public class User{
  3. public class test{
  4. public User print(){
  5. return User.this;
  6. }
  7. }
  8. }
  9. //.new使用实例
  10. public class User{
  11. class test1{
  12. private int i = 1;
  13. public int value(){return i;}
  14. }
  15. class test2{
  16. private int i = 2;
  17. public int value(){return i;}
  18. test2(int i){
  19. this.i = i;
  20. }
  21. }
  22. }
  23. psvm{
  24. User u = new User();
  25. User.test1 t1 = u.new test1();
  26. User.test2 t2 = u.new test2(4);
  27. //伪代码
  28. sout->t1.value();
  29. sout->t2.value()
  30. }

转型:当一个内部类向上转型为基类&接口时,获取到的引用其实是指向的基类&引用,方便隐藏实现细节。

  1. public interface Destination{
  2. String readLabel();
  3. }
  4. public interface Contents{
  5. int value();
  6. }
  7. class Parcel4 {
  8. private class PContents implements Contents {
  9. private int i = 11;
  10. @Override
  11. public int value() { return i; }
  12. }
  13. protected final class PDestination implements Destination {
  14. private String label;
  15. private PDestination(String whereTo) {
  16. label = whereTo;
  17. }
  18. @Override
  19. public String readLabel() { return label; }
  20. }
  21. public Destination destination(String s) {
  22. return new PDestination(s);
  23. }
  24. public Contents contents() {
  25. return new PContents();
  26. }
  27. }
  28. public class TestParcel {
  29. public static void main(String[] args) {
  30. Parcel4 p = new Parcel4();
  31. Contents c = p.contents();
  32. Destination d = p.destination("Tasmania");
  33. // Illegal -- can't access private class:
  34. //- Parcel4.PContents pc = p.new PContents();
  35. }
  36. }

异常

Java~结构不佳的程序不能运行。

1.体系结构

Java编程思想 - 图1
1、Java中的异常、错误都继承自java.lang包下的Throwable类。
2、Throwable下提供Exception、Error两个子类。
3、Exception下提供Checked Exception、Unchecked Exception两种异常。
4、Checked Exception下又包含RunntimeException、IO、SQLException等。

2.Exception&Error

相同点:
两者都继承自java.lang包下的Throwable父类。
不同点:
Exception通常是程序自身可以进行处理的,可以抛出给上级调用者处理,获取直接捕获进行自身处理;
Error通常指的是程序无法处理的错误,更多的是JVM运行时内存不足等问题,这是会直接结束线程的运行。

3.必检异常&免检异常

CheckException:必检异常,不进行捕获或者抛出则无法编译通过。
UnCheckedException:免检异常,通常指的是RunntimeException及其子类(空指针、数组下标越界……)

4.Throwable常用方法

String getMessage() 获取简要信息
String toString() 获取详细信息
String getLocalizedMessage() 返回异常信息的本地化信息
void printStackTrace() 打印Throwable封装的异常信息

泛型&反射

1.泛型

界定:泛型是JDK5中提出的新特性,是一种对类型约束的限制解除,编译器进行泛型的安全转型。
类型:泛型类、泛型接口、泛型参数、泛型方法。

  1. //此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
  2. //在实例化泛型类时,必须指定T的具体类型
  3. public class Generic<T>{
  4. private T key;
  5. public Generic(T key) {
  6. this.key = key;
  7. }
  8. public T getKey(){
  9. return key;
  10. }
  11. }
  12. // 泛型接口
  13. public interface Generator<T> {
  14. public T method();
  15. }
  16. // 泛型方法
  17. public static < E > void printArray( E[] inputArray )
  18. {
  19. for ( E element : inputArray ){
  20. System.out.printf( "%s ", element );
  21. }
  22. System.out.println();
  23. }
  1. **泛型擦除:**<br />下面代码中,clazz1clazz2起初一看是不同的类型,但实际上是相同的类型。
  1. public class solution{
  2. public static void main(String[] args){
  3. Class clazz1 = new ArrayList<String>().getClass();
  4. Class clazz2 = new ArrayList<Integer>().getClass();
  5. class1 != class2;
  6. }
  7. }
  1. 这是因为,Java在**编译期间**会对泛型进行擦除。如果指定了边界,则会擦除到第一个边界,无边界,则擦除到Object。<br />**边界:**<br />参数泛型化的适用范围,指明泛型表示的类型范围。<br />**通配符:**<br />无界通配符:<?><br />上界通配符:<? extends T>。表示只能存放父类、及其父类的派生类。<br />![](https://cdn.nlark.com/yuque/0/2022/webp/27397677/1653895994482-12e50c8d-baac-4c78-902b-83d0f57a5955.webp#clientId=u85a0d0c9-6fcc-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=udc17364c&margin=%5Bobject%20Object%5D&originHeight=349&originWidth=720&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=ud68a4b7a-130f-4638-87b8-1bd2aae98df&title=)<br />下界通配符:<? supper T>。表示只能存放父类、及其父类的父类。<br />![](https://cdn.nlark.com/yuque/0/2022/webp/27397677/1653896098452-d4ed3e5f-0fee-4ca9-885f-e81ad3ece2e2.webp#clientId=u85a0d0c9-6fcc-4&crop=0&crop=0&crop=1&crop=1&from=paste&id=udf0de37e&margin=%5Bobject%20Object%5D&originHeight=370&originWidth=720&originalType=url&ratio=1&rotation=0&showTitle=false&status=done&style=none&taskId=u5b24808f-59ac-4ea1-8096-9cb8c5762de&title=)

2.RTTI&反射

界定:RTTI(运行时类型识别)、反射都是可以在编译期获取类型信息的方式,RTTI更加传统一些。
Class对象:每一个类都对应一个Class对象,包含类的所有信息。通常在使用的时候才进行加载。
特点:
反射可以使得编码更加灵活多变。
但是一定程度上也增加了不安全性。

3.三种获取方式

  1. Class.forName("类的全限定名");
  2. obj.getClass();
  3. 类名.class;

常见类

1.Object

Object是所有类的基类、其中提供了hashCode()、equals()等方法。

  1. /**
  2. * native 方法,用于返回对象的哈希码,主要使用在哈希表中,比如 JDK 中的HashMap。
  3. */
  4. public native int hashCode()
  5. /**
  6. * 用于比较 2 个对象的内存地址是否相等,String 类对该方法进行了重写以用于比较字符串的值是否相等。
  7. */
  8. public boolean equals(Object obj)
  9. /**
  10. * naitive 方法,用于创建并返回当前对象的一份拷贝。
  11. */
  12. protected native Object clone() throws CloneNotSupportedException
  13. /**
  14. * 返回类的名字实例的哈希码的 16 进制的字符串。建议 Object 所有的子类都重写这个方法。
  15. */
  16. public String toString()
  17. /**
  18. * native 方法,并且不能重写。唤醒一个在此对象监视器上等待的线程(监视器相当于就是锁的概念)。如果有多个线程在等待只会任意唤醒一个。
  19. */
  20. public final native void notify()
  21. /**
  22. * native 方法,并且不能重写。跟 notify 一样,唯一的区别就是会唤醒在此对象监视器上等待的所有线程,而不是一个线程。
  23. */
  24. public final native void notifyAll()
  25. /**
  26. * native方法,并且不能重写。暂停线程的执行。注意:sleep 方法没有释放锁,而 wait 方法释放了锁 ,timeout 是等待时间。
  27. */
  28. public final native void wait(long timeout) throws InterruptedException
  29. /**
  30. * 多了 nanos 参数,这个参数表示额外时间(以毫微秒为单位,范围是 0-999999)。 所以超时的时间还需要加上 nanos 毫秒。。
  31. */
  32. public final void wait(long timeout, int nanos) throws InterruptedException
  33. /**
  34. * 跟之前的2个wait方法一样,只不过该方法一直等待,没有超时时间这个概念
  35. */
  36. public final void wait() throws InterruptedException

2.String

1.String为何不可变?

1.String类本身被final修饰、防止了该类被继承而进行破坏;
2.String类中的字符数组也被final修饰,且私有化。阻止了对外暴露且进行修改。
被final修饰的类不能被继承、修饰的方法不能被重写、修饰的变量不能进行重新定义赋值。

  1. public final class String
  2. implements java.io.Serializable, Comparable<String>, CharSequence {
  3. /** The value is used for character storage. */
  4. private final char value[];
  5. }

2.String&StringBuilder&StringBuffer

可变性:String不可变;StringBuilder和StringBuffer均为可变字符串。
线程安全:StringBuffer线程安全,使用synchronized方法锁。

  1. /**
  2. * @throws IndexOutOfBoundsException {@inheritDoc}
  3. */
  4. @Override
  5. public synchronized StringBuffer insert(int offset, char c) {
  6. toStringCache = null;
  7. super.insert(offset, c);
  8. return this;
  9. }

3.==&equals()

基本类型:
==比较的是值、equals()无法进行判断
引用类型:
==比较的是对象内存地址,equals()比较的是对象地址,重写后比较的是对象的值。

4.equals()

Object中的equals()未经过重写、比较的是对象的内存地址;
String中的equals()经过重写,比较的是对象的值。

5.hashCode()

hashCode()作用就是获取“散列码”,实际上是一个int类型的整数、确定对象在散列表中的索引位置。