diff --git a/Java基础教程/Java语言基础/03 函数方法.md b/Java基础教程/Java语言基础/03 函数方法.md index f4ab426a..de9bf5ef 100644 --- a/Java基础教程/Java语言基础/03 函数方法.md +++ b/Java基础教程/Java语言基础/03 函数方法.md @@ -34,7 +34,7 @@ Java方法是语句的集合,在一起执行一个功能。 * 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。 * 返回值类型 :方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void。 * 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。 -* 参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。 +* 参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。包括参数类型和参数名。 * 方法体:方法体包含具体的语句,定义该方法的功能。 diff --git a/Java基础教程/Java语言基础/05 面向对象.md b/Java基础教程/Java语言基础/05 面向对象.md index 2509688f..ab33d9ca 100644 --- a/Java基础教程/Java语言基础/05 面向对象.md +++ b/Java基础教程/Java语言基础/05 面向对象.md @@ -1,8 +1,12 @@ ## 1 类和对象 -### 定义 +### 类的定义 -属性和方法(变量和函数)。放到一起就是对象。 +属性和方法(变量和函数),对象即实例。放到一起就是对象。面相对象的本质就是以类的方式组织代码,以对象组织封装数据。 + +抽象,把共同的部分抽取出来,组成一个类。 + +一个项目应该只存在一个主启动类。 * 对象:对象是类的一个实例 * 类:类是一个模板,它描述一类对象的行为和状态。 @@ -28,560 +32,63 @@ public class Dog { } ``` -### - -## 2 三大特性 -## 封装 - -## 继承 - -## 多态 - -## 3 特殊类 -## 抽象类 - - -## 接口 - -## 内部类 - -## 五、Object 通用方法 - -### 概览 +* **final关键字** 可以用来修饰变量(包括类属性、对象属性、局部变量和形参)、方法(包括类方法和对象方法)和类。使用 final 关键字声明类,就是把类定义定义为最终类,不能被继承,或者用于修饰方法,该方法不能被子类重写 ```java - -public native int hashCode() - -public boolean equals(Object obj) - -protected native Object clone() throws CloneNotSupportedException - -public String toString() - -public final native Class getClass() - -protected void finalize() throws Throwable {} - -public final native void notify() - -public final native void notifyAll() - -public final native void wait(long timeout) throws InterruptedException - -public final void wait(long timeout, int nanos) throws InterruptedException - -public final void wait() throws InterruptedException +final class 类名 {//类体} ``` -### equals() -**1. 等价关系** -两个对象具有等价关系,需要满足以下五个条件: +### 变量类型 -Ⅰ 自反性 +* 局部变量:在方法、构造方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在方法中,方法结束后,变量就会自动销毁。 +* 成员变量:成员变量是定义在类中,方法体之外的变量。这种变量在创建对象的时候实例化。成员变量可以被类中方法、构造方法和特定类的语句块访问。只能通过实例化的对象进行访问 +* 类变量:类变量也声明在类中,方法体之外,但必须声明为 static 类型。只能通过类名进行访问 + + +### 构造方法 +1. 每个类都有构造方法。如果没有显式地为类定义构造方法,Java 编译器将会为该类提供一个默认构造方法。一旦定义了有参构造,无参构造就需要显示定义。 +2. 在创建一个对象的时候,至少要调用一个构造方法。构造方法的名称必须与类同名,一个类可以有多个构造方法。 +3. 和类名相同,没有返回值,一般为public。 ```java -x.equals(x); // true -``` - -Ⅱ 对称性 - -```java -x.equals(y) == y.equals(x); // true -``` - -Ⅲ 传递性 - -```java -if (x.equals(y) && y.equals(z)) - x.equals(z); // true; -``` - -Ⅳ 一致性 - -多次调用 equals() 方法结果不变 - -```java -x.equals(y) == x.equals(y); // true -``` - -Ⅴ 与 null 的比较 - -对任何不是 null 的对象 x 调用 x.equals(null) 结果都为 false - -```java -x.equals(null); // false; -``` - -**2. 等价与相等** - -- 对于基本类型,== 判断两个值是否相等,基本类型没有 equals() 方法。 -- 对于引用类型,== 判断两个变量是否引用同一个对象,而 equals() 判断引用的对象是否等价。 - -```java -Integer x = new Integer(1); -Integer y = new Integer(1); -System.out.println(x.equals(y)); // true -System.out.println(x == y); // false -``` - -**3. 实现** - -- 检查是否为同一个对象的引用,如果是直接返回 true; -- 检查是否是同一个类型,如果不是,直接返回 false; -- 将 Object 对象进行转型; -- 判断每个关键域是否相等。 - -```java -public class EqualExample { - - private int x; - private int y; - private int z; - - public EqualExample(int x, int y, int z) { - this.x = x; - this.y = y; - this.z = z; +public class Puppy{ + public Puppy(){ } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - EqualExample that = (EqualExample) o; - - if (x != that.x) return false; - if (y != that.y) return false; - return z == that.z; + + public Puppy(String name){ + // 这个构造器仅有一个参数:name } } ``` -### hashCode() +### 对象创建 +* 声明:声明一个对象,包括对象名称和对象类型。 +* 实例化:使用关键字 new 来创建一个对象。 +* 初始化:使用 new 创建对象时,会调用构造方法初始化对象。 -hashCode() 返回哈希值,而 equals() 是用来判断两个对象是否等价。等价的两个对象散列值一定相同,但是散列值相同的两个对象不一定等价,这是因为计算哈希值具有随机性,两个值不同的对象可能计算出相同的哈希值。 +### 访问对象 -在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证等价的两个对象哈希值也相等。 - -HashSet 和 HashMap 等集合类使用了 hashCode() 方法来计算对象应该存储的位置,因此要将对象添加到这些集合类中,需要让对应的类实现 hashCode() 方法。 - -下面的代码中,新建了两个等价的对象,并将它们添加到 HashSet 中。我们希望将这两个对象当成一样的,只在集合中添加一个对象。但是 EqualExample 没有实现 hashCode() 方法,因此这两个对象的哈希值是不同的,最终导致集合添加了两个等价的对象。 +1. 访问对象的成员变量(属性) +2. 访问对象的函数成员(方法) +3. **this关键字**:指向自己的引用。采用 this 关键字是为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突。访问当前对象的实例变量。 +4. **super关键字**:我们可以通过super关键字来实现对父类成员的访问,用来引用当前对象的父类。 ```java -EqualExample e1 = new EqualExample(1, 1, 1); -EqualExample e2 = new EqualExample(1, 1, 1); -System.out.println(e1.equals(e2)); // true -HashSet set = new HashSet<>(); -set.add(e1); -set.add(e2); -System.out.println(set.size()); // 2 -``` +/* 实例化对象 */ +Object referenceVariable = new Constructor(); +/* 访问类中的变量 */ +referenceVariable.variableName; +/* 访问类中的方法 */ +referenceVariable.methodName(); -理想的哈希函数应当具有均匀性,即不相等的对象应当均匀分布到所有可能的哈希值上。这就要求了哈希函数要把所有域的值都考虑进来。可以将每个域都当成 R 进制的某一位,然后组成一个 R 进制的整数。 - -R 一般取 31,因为它是一个奇素数,如果是偶数的话,当出现乘法溢出,信息就会丢失,因为与 2 相乘相当于向左移一位,最左边的位丢失。并且一个数与 31 相乘可以转换成移位和减法:`31*x == (x<<5)-x`,编译器会自动进行这个优化。 - -```java -@Override -public int hashCode() { - int result = 17; - result = 31 * result + x; - result = 31 * result + y; - result = 31 * result + z; - return result; +​ +public void setName(String name){ + this.name = name; } ``` -### toString() - -默认返回 ToStringExample@4554617c 这种形式,其中 @ 后面的数值为散列码的无符号十六进制表示。 - -```java -public class ToStringExample { - - private int number; - - public ToStringExample(int number) { - this.number = number; - } -} -``` - -```java -ToStringExample example = new ToStringExample(123); -System.out.println(example.toString()); -``` - -```html -ToStringExample@4554617c -``` - -### clone() - -**1. cloneable** - -clone() 是 Object 的 protected 方法,它不是 public,一个类不显式去重写 clone(),其它类就不能直接去调用该类实例的 clone() 方法。 - -```java -public class CloneExample { - private int a; - private int b; -} -``` - -```java -CloneExample e1 = new CloneExample(); -// CloneExample e2 = e1.clone(); // 'clone()' has protected access in 'java.lang.Object' -``` - -重写 clone() 得到以下实现: - -```java -public class CloneExample { - private int a; - private int b; - - @Override - public CloneExample clone() throws CloneNotSupportedException { - return (CloneExample)super.clone(); - } -} -``` - -```java -CloneExample e1 = new CloneExample(); -try { - CloneExample e2 = e1.clone(); -} catch (CloneNotSupportedException e) { - e.printStackTrace(); -} -``` - -```html -java.lang.CloneNotSupportedException: CloneExample -``` - -以上抛出了 CloneNotSupportedException,这是因为 CloneExample 没有实现 Cloneable 接口。 - -应该注意的是,clone() 方法并不是 Cloneable 接口的方法,而是 Object 的一个 protected 方法。Cloneable 接口只是规定,如果一个类没有实现 Cloneable 接口又调用了 clone() 方法,就会抛出 CloneNotSupportedException。 - -```java -public class CloneExample implements Cloneable { - private int a; - private int b; - - @Override - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } -} -``` - -**2. 浅拷贝** - -拷贝对象和原始对象的引用类型引用同一个对象。 - -```java -public class ShallowCloneExample implements Cloneable { - - private int[] arr; - - public ShallowCloneExample() { - arr = new int[10]; - for (int i = 0; i < arr.length; i++) { - arr[i] = i; - } - } - - public void set(int index, int value) { - arr[index] = value; - } - - public int get(int index) { - return arr[index]; - } - - @Override - protected ShallowCloneExample clone() throws CloneNotSupportedException { - return (ShallowCloneExample) super.clone(); - } -} -``` - -```java -ShallowCloneExample e1 = new ShallowCloneExample(); -ShallowCloneExample e2 = null; -try { - e2 = e1.clone(); -} catch (CloneNotSupportedException e) { - e.printStackTrace(); -} -e1.set(2, 222); -System.out.println(e2.get(2)); // 222 -``` - -**3. 深拷贝** - -拷贝对象和原始对象的引用类型引用不同对象。 - -```java -public class DeepCloneExample implements Cloneable { - - private int[] arr; - - public DeepCloneExample() { - arr = new int[10]; - for (int i = 0; i < arr.length; i++) { - arr[i] = i; - } - } - - public void set(int index, int value) { - arr[index] = value; - } - - public int get(int index) { - return arr[index]; - } - - @Override - protected DeepCloneExample clone() throws CloneNotSupportedException { - DeepCloneExample result = (DeepCloneExample) super.clone(); - result.arr = new int[arr.length]; - for (int i = 0; i < arr.length; i++) { - result.arr[i] = arr[i]; - } - return result; - } -} -``` - -```java -DeepCloneExample e1 = new DeepCloneExample(); -DeepCloneExample e2 = null; -try { - e2 = e1.clone(); -} catch (CloneNotSupportedException e) { - e.printStackTrace(); -} -e1.set(2, 222); -System.out.println(e2.get(2)); // 2 -``` - -**4. clone() 的替代方案** - -使用 clone() 方法来拷贝一个对象即复杂又有风险,它会抛出异常,并且还需要类型转换。Effective Java 书上讲到,最好不要去使用 clone(),可以使用拷贝构造函数或者拷贝工厂来拷贝一个对象。 - -```java -public class CloneConstructorExample { - - private int[] arr; - - public CloneConstructorExample() { - arr = new int[10]; - for (int i = 0; i < arr.length; i++) { - arr[i] = i; - } - } - - public CloneConstructorExample(CloneConstructorExample original) { - arr = new int[original.arr.length]; - for (int i = 0; i < original.arr.length; i++) { - arr[i] = original.arr[i]; - } - } - - public void set(int index, int value) { - arr[index] = value; - } - - public int get(int index) { - return arr[index]; - } -} -``` - -```java -CloneConstructorExample e1 = new CloneConstructorExample(); -CloneConstructorExample e2 = new CloneConstructorExample(e1); -e1.set(2, 222); -System.out.println(e2.get(2)); // 2 -``` - -## 六、继承 - -### 访问权限 - -Java 中有三个访问权限修饰符:private、protected 以及 public,如果不加访问修饰符,表示包级可见。 - -可以对类或类中的成员(字段和方法)加上访问修饰符。 - -- 类可见表示其它类可以用这个类创建实例对象。 -- 成员可见表示其它类可以用这个类的实例对象访问到该成员; - -protected 用于修饰成员,表示在继承体系中成员对于子类可见,但是这个访问修饰符对于类没有意义。 - -设计良好的模块会隐藏所有的实现细节,把它的 API 与它的实现清晰地隔离开来。模块之间只通过它们的 API 进行通信,一个模块不需要知道其他模块的内部工作情况,这个概念被称为信息隐藏或封装。因此访问权限应当尽可能地使每个类或者成员不被外界访问。 - -如果子类的方法重写了父类的方法,那么子类中该方法的访问级别不允许低于父类的访问级别。这是为了确保可以使用父类实例的地方都可以使用子类实例去代替,也就是确保满足里氏替换原则。 - -字段决不能是公有的,因为这么做的话就失去了对这个字段修改行为的控制,客户端可以对其随意修改。例如下面的例子中,AccessExample 拥有 id 公有字段,如果在某个时刻,我们想要使用 int 存储 id 字段,那么就需要修改所有的客户端代码。 - -```java -public class AccessExample { - public String id; -} -``` - -可以使用公有的 getter 和 setter 方法来替换公有字段,这样的话就可以控制对字段的修改行为。 - -```java -public class AccessExample { - - private int id; - - public String getId() { - return id + ""; - } - - public void setId(String id) { - this.id = Integer.valueOf(id); - } -} -``` - -但是也有例外,如果是包级私有的类或者私有的嵌套类,那么直接暴露成员不会有特别大的影响。 - -```java -public class AccessWithInnerClassExample { - - private class InnerClass { - int x; - } - - private InnerClass innerClass; - - public AccessWithInnerClassExample() { - innerClass = new InnerClass(); - } - - public int getValue() { - return innerClass.x; // 直接访问 - } -} -``` - -### 抽象类与接口 - -**1. 抽象类** - -抽象类和抽象方法都使用 abstract 关键字进行声明。如果一个类中包含抽象方法,那么这个类必须声明为抽象类。 - -抽象类和普通类最大的区别是,抽象类不能被实例化,只能被继承。 - -```java -public abstract class AbstractClassExample { - - protected int x; - private int y; - - public abstract void func1(); - - public void func2() { - System.out.println("func2"); - } -} -``` - -```java -public class AbstractExtendClassExample extends AbstractClassExample { - @Override - public void func1() { - System.out.println("func1"); - } -} -``` - -```java -// AbstractClassExample ac1 = new AbstractClassExample(); // 'AbstractClassExample' is abstract; cannot be instantiated -AbstractClassExample ac2 = new AbstractExtendClassExample(); -ac2.func1(); -``` - -**2. 接口** - -接口是抽象类的延伸,在 Java 8 之前,它可以看成是一个完全抽象的类,也就是说它不能有任何的方法实现。 - -从 Java 8 开始,接口也可以拥有默认的方法实现,这是因为不支持默认方法的接口的维护成本太高了。在 Java 8 之前,如果一个接口想要添加新的方法,那么要修改所有实现了该接口的类,让它们都实现新增的方法。 - -接口的成员(字段 + 方法)默认都是 public 的,并且不允许定义为 private 或者 protected。从 Java 9 开始,允许将方法定义为 private,这样就能定义某些复用的代码又不会把方法暴露出去。 - -接口的字段默认都是 static 和 final 的。 - -```java -public interface InterfaceExample { - - void func1(); - - default void func2(){ - System.out.println("func2"); - } - - int x = 123; - // int y; // Variable 'y' might not have been initialized - public int z = 0; // Modifier 'public' is redundant for interface fields - // private int k = 0; // Modifier 'private' not allowed here - // protected int l = 0; // Modifier 'protected' not allowed here - // private void fun3(); // Modifier 'private' not allowed here -} -``` - -```java -public class InterfaceImplementExample implements InterfaceExample { - @Override - public void func1() { - System.out.println("func1"); - } -} -``` - -```java -// InterfaceExample ie1 = new InterfaceExample(); // 'InterfaceExample' is abstract; cannot be instantiated -InterfaceExample ie2 = new InterfaceImplementExample(); -ie2.func1(); -System.out.println(InterfaceExample.x); -``` - -**3. 比较** - -- 从设计层面上看,抽象类提供了一种 IS-A 关系,需要满足里式替换原则,即子类对象必须能够替换掉所有父类对象。而接口更像是一种 LIKE-A 关系,它只是提供一种方法实现契约,并不要求接口和实现接口的类具有 IS-A 关系。 -- 从使用上来看,一个类可以实现多个接口,但是不能继承多个抽象类。 -- 接口的字段只能是 static 和 final 类型的,而抽象类的字段没有这种限制。 -- 接口的成员只能是 public 的,而抽象类的成员可以有多种访问权限。 - -**4. 使用选择** - -使用接口: - -- 需要让不相关的类都实现一个方法,例如不相关的类都可以实现 Comparable 接口中的 compareTo() 方法; -- 需要使用多重继承。 - -使用抽象类: - -- 需要在几个相关的类中共享代码。 -- 需要能控制继承来的成员的访问权限,而不是都为 public。 -- 需要继承非静态和非常量字段。 - -在很多情况下,接口优先于抽象类。因为接口没有抽象类严格的类层次结构要求,可以灵活地为一个类添加行为。并且从 Java 8 开始,接口也可以有默认的方法实现,使得修改接口的成本也变的很低。 - -- [Abstract Methods and Classes](https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html) -- [深入理解 abstract class 和 interface](https://www.ibm.com/developerworks/cn/java/l-javainterface-abstract/) -- [When to Use Abstract Class and Interface](https://dzone.com/articles/when-to-use-abstract-class-and-intreface) -- [Java 9 Private Methods in Interfaces](https://www.journaldev.com/12850/java-9-private-methods-interfaces) ### super @@ -624,23 +131,216 @@ public class SuperExtendExample extends SuperExample { } ``` + +## 2 三大特性——封装 +高内聚、低耦合。属性私有 + +1. 隐藏实现的细节。将抽象性函式接口的实现细节部分包装、隐藏起来的方法。 +2. 提高系统的安全性。在getset中对输入数据进行安全检查。封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。要访问该类的代码和数据,必须通过严格的接口控制。 +3. 提供统一的接口 +4. 更容易理解与维护,也加强了程式码的安全性。 + + +**实现封装的步骤** + +1. 修改属性的可见性来限制对属性的访问(一般限制为private) +2. 对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问。get/set方法 + +## 3 三大特性——继承 + +**继承的定义** +1. 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。 +2. 继承本质上是一种代码复用的方法。也提高了代码的耦合程度。 + ```java -SuperExample e = new SuperExtendExample(1, 2, 3); -e.func(); +class 父类 { +} + +class 子类 extends 父类 { +} +``` +**继承的特性** +1. Java不支持多继承。但是能够层级多重继承。 +2. 子类拥有父类非 private 的属性、方法。子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。子类可以用自己的方式实现父类的方法。 + +```java + +public class Animal { + private String name; + private int id; + public Animal(String myName, int myid) { + //初始化属性值 + } + public void eat() { //吃东西方法的具体实现 } + public void sleep() { //睡觉方法的具体实现 } +} + +public class Penguin extends Animal{ +} +``` +**继承的构造器** +* 子类是不继承父类的构造器(构造方法或者构造函数)的,它只能调用(隐式或显式)父类的构造器。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。 +* 如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。 + +```java +class SuperClass { + private int n; + SuperClass(){ + System.out.println("SuperClass()"); + } + SuperClass(int n) { + System.out.println("SuperClass(int n)"); + this.n = n; + } +} +// SubClass 类继承 +class SubClass extends SuperClass{ + private int n; + + SubClass(){ // 自动调用父类的无参数构造器 + System.out.println("SubClass"); + } + + public SubClass(int n){ + super(300); // 调用父类中带有参数的构造器 + System.out.println("SubClass(int n):"+n); + this.n = n; + } +} +// SubClass2 类继承 +class SubClass2 extends SuperClass{ + private int n; + + SubClass2(){ + super(300); // 调用父类中带有参数的构造器 + System.out.println("SubClass2"); + } + + public SubClass2(int n){ // 自动调用父类的无参数构造器 + System.out.println("SubClass2(int n):"+n); + this.n = n; + } +} +public class TestSuperSub{ + public static void main (String args[]){ + System.out.println("------SubClass 类继承------"); + SubClass sc1 = new SubClass(); + SubClass sc2 = new SubClass(100); + System.out.println("------SubClass2 类继承------"); + SubClass2 sc3 = new SubClass2(); + SubClass2 sc4 = new SubClass2(200); + } +} +``` +## 4 三大特性——多态 + +**多态的定义** +多态是同一个行为具有多个不同表现形式或形态的能力。多态就是同一个接口,使用不同的实例而执行不同操作。 +1. 消除类型之间的耦合关系 +2. 可替换性 +3. 可扩充性 +4. 接口性 +5. 灵活性 +6. 简化性 + +**多态的条件** + +* 继承 +* 重写 +* 父类引用指向子类对象:Parent p = new Child(); +![](image/2022-07-11-15-48-30.png) + +```java +class Shape { + void draw() {} +} + +class Circle extends Shape { + void draw() { + System.out.println("Circle.draw()"); + } +} + +class Square extends Shape { + void draw() { + System.out.println("Square.draw()"); + } +} + +class Triangle extends Shape { + void draw() { + System.out.println("Triangle.draw()"); + } +} ``` -```html -SuperExample.func() -SuperExtendExample.func() +**多态的原理** +在C++中只有声明了虚函数,程序在执行过程中才会从虚函数表中查找并执行子类的方法。但是在Java中所有的函数默认都是虚函数。只要被重写,在执行过程中,就一定会调用具体对象的方法。变量的类型不重要,重要的是对象的类型。 +* 如果 Java 中不希望某个函数具有虚函数特性,可以加上 final 关键字变成非虚函数。 +* 哪个类的实例对象,就调用哪个对象的方法。与变量的类型不是强相关的。 + +```java +public class Test { + public static void main(String[] args) { + show(new Cat()); // 以 Cat 对象调用 show 方法 + show(new Dog()); // 以 Dog 对象调用 show 方法 + + Animal a = new Cat(); // 向上转型 + a.eat(); // 调用的是 Cat 的 eat + Cat c = (Cat)a; // 向下转型 + c.work(); // 调用的是 Cat 的 work + } + + public static void show(Animal a) { + a.eat(); + // 类型判断 + if (a instanceof Cat) { // 猫做的事情 + Cat c = (Cat)a; + c.work(); + } else if (a instanceof Dog) { // 狗做的事情 + Dog c = (Dog)a; + c.work(); + } + } +} + +abstract class Animal { + abstract void eat(); +} + +class Cat extends Animal { + public void eat() { + System.out.println("吃鱼"); + } + public void work() { + System.out.println("抓老鼠"); + } +} + +class Dog extends Animal { + public void eat() { + System.out.println("吃骨头"); + } + public void work() { + System.out.println("看家"); + } +} ``` -[Using the Keyword super](https://docs.oracle.com/javase/tutorial/java/IandI/super.html) +**多态实现方法** -### 重写与重载 +1. 重载和重写。 +2. 接口实现 +3. 抽象类和抽象方法 -**1. 重写(Override)** -存在于继承体系中,指子类实现了一个与父类在方法声明上完全相同的一个方法。 +## 6 重写与重载 +### 定义 +重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写! + +* 子类能够重写父类的方法。当子类对象调用重写的方法时,调用的是子类的方法,而不是父类中被重写的方法。要想调用父类中被重写的方法,则必须使用关键字 super。 + +* 重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。 为了满足里式替换原则,重写有以下三个限制: @@ -650,174 +350,54 @@ SuperExtendExample.func() 使用 @Override 注解,可以让编译器帮忙检查是否满足上面的三个限制条件。 -下面的示例中,SubClass 为 SuperClass 的子类,SubClass 重写了 SuperClass 的 func() 方法。其中: - -- 子类方法访问权限为 public,大于父类的 protected。 -- 子类的返回类型为 ArrayList\,是父类返回类型 List\ 的子类。 -- 子类抛出的异常类型为 Exception,是父类抛出异常 Throwable 的子类。 -- 子类重写方法使用 @Override 注解,从而让编译器自动检查是否满足限制条件。 - ```java -class SuperClass { - protected List func() throws Throwable { - return new ArrayList<>(); - } +class Animal{ + public void move(){ + System.out.println("动物可以移动"); + } } - -class SubClass extends SuperClass { - @Override - public ArrayList func() throws Exception { - return new ArrayList<>(); - } + +class Dog extends Animal{ + public void move(){ + System.out.println("狗可以跑和走"); + } +} + +public class TestDog{ + public static void main(String args[]){ + Animal a = new Animal(); // Animal 对象 + Animal b = new Dog(); // Dog 对象 + + a.move();// 执行 Animal 类的方法 + + b.move();//执行 Dog 类的方法 + } } ``` +### 重写的原则 +* 参数列表与被重写方法的参数列表必须完全相同。 +* 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类 +* 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected。 +* 父类的成员方法只能被它的子类重写。声明为 final 的方法不能被重写。声明为 static 的方法不能被重写,但是能够被再次声明。 +* 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。 +* 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。 +* 构造方法不能被重写。如果不能继承一个类,则不能重写该类的方法。 + +### 与重载的区别 + +* 重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。而重写是在父类和子类之间,发生继承关系后,进行重写,返回值必须具有一致性。 +* 每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。每个重写的方法都必须有相同的参数列表。 +* 在子类中如果不进行重写,则继承了父类中的方法,即可对父类中的方法进行扩展和重载。 +* 方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。重载又叫编译时多态。重写又叫运行时多态。 + +![](image/2022-07-11-17-17-10.png) + + +### 方法访问的优先级 在调用一个方法时,先从本类中查找看是否有对应的方法,如果没有再到父类中查看,看是否从父类继承来。否则就要对参数进行转型,转成父类之后看是否有对应的方法。总的来说,方法调用的优先级为: - this.func(this) - super.func(this) - this.func(super) - super.func(super) - - -```java -/* - A - | - B - | - C - | - D - */ - - -class A { - - public void show(A obj) { - System.out.println("A.show(A)"); - } - - public void show(C obj) { - System.out.println("A.show(C)"); - } -} - -class B extends A { - - @Override - public void show(A obj) { - System.out.println("B.show(A)"); - } -} - -class C extends B { -} - -class D extends C { -} -``` - -```java -public static void main(String[] args) { - - A a = new A(); - B b = new B(); - C c = new C(); - D d = new D(); - - // 在 A 中存在 show(A obj),直接调用 - a.show(a); // A.show(A) - // 在 A 中不存在 show(B obj),将 B 转型成其父类 A - a.show(b); // A.show(A) - // 在 B 中存在从 A 继承来的 show(C obj),直接调用 - b.show(c); // A.show(C) - // 在 B 中不存在 show(D obj),但是存在从 A 继承来的 show(C obj),将 D 转型成其父类 C - b.show(d); // A.show(C) - - // 引用的还是 B 对象,所以 ba 和 b 的调用结果一样 - A ba = new B(); - ba.show(c); // A.show(C) - ba.show(d); // A.show(C) -} -``` - -**2. 重载(Overload)** - -存在于同一个类中,指一个方法与已经存在的方法名称上相同,但是参数类型、个数、顺序至少有一个不同。 - -应该注意的是,返回值不同,其它都相同不算是重载。 - -```java -class OverloadingExample { - public void show(int x) { - System.out.println(x); - } - - public void show(int x, String y) { - System.out.println(x + " " + y); - } -} -``` - -```java -public static void main(String[] args) { - OverloadingExample example = new OverloadingExample(); - example.show(1); - example.show(1, "2"); -} -``` - -## 七、反射 - -每个类都有一个 **Class** 对象,包含了与类有关的信息。当编译一个新类时,会产生一个同名的 .class 文件,该文件内容保存着 Class 对象。 - -类加载相当于 Class 对象的加载,类在第一次使用时才动态加载到 JVM 中。也可以使用 `Class.forName("com.mysql.jdbc.Driver")` 这种方式来控制类的加载,该方法会返回一个 Class 对象。 - -反射可以提供运行时的类信息,并且这个类可以在运行时才加载进来,甚至在编译时期该类的 .class 不存在也可以加载进来。 - -Class 和 java.lang.reflect 一起对反射提供了支持,java.lang.reflect 类库主要包含了以下三个类: - -- **Field** :可以使用 get() 和 set() 方法读取和修改 Field 对象关联的字段; -- **Method** :可以使用 invoke() 方法调用与 Method 对象关联的方法; -- **Constructor** :可以用 Constructor 的 newInstance() 创建新的对象。 - -**反射的优点:** - -- **可扩展性** :应用程序可以利用全限定名创建可扩展对象的实例,来使用来自外部的用户自定义类。 -- **类浏览器和可视化开发环境** :一个类浏览器需要可以枚举类的成员。可视化开发环境(如 IDE)可以从利用反射中可用的类型信息中受益,以帮助程序员编写正确的代码。 -- **调试器和测试工具** : 调试器需要能够检查一个类里的私有成员。测试工具可以利用反射来自动地调用类里定义的可被发现的 API 定义,以确保一组测试中有较高的代码覆盖率。 - -**反射的缺点:** - -尽管反射非常强大,但也不能滥用。如果一个功能可以不用反射完成,那么最好就不用。在我们使用反射技术时,下面几条内容应该牢记于心。 - -- **性能开销** :反射涉及了动态类型的解析,所以 JVM 无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被执行的代码或对性能要求很高的程序中使用反射。 - -- **安全限制** :使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行,如 Applet,那么这就是个问题了。 - -- **内部暴露** :由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用,这可能导致代码功能失调并破坏可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化。 - -- [Trail: The Reflection API](https://docs.oracle.com/javase/tutorial/reflect/index.html) -- [深入解析 Java 反射(1)- 基础](http://www.sczyh30.com/posts/Java/java-reflection-1/) - - -## 九、泛型 - -```java -public class Box { - // T stands for "Type" - private T t; - public void set(T t) { this.t = t; } - public T get() { return t; } -} -``` - -- [Java 泛型详解](https://www.cnblogs.com/Blue-Keroro/p/8875898.html) -- [10 道 Java 泛型面试题](https://cloud.tencent.com/developer/article/1033693) - -## 十、注解 - -Java 注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。 - -[注解 Annotation 实现原理与自定义注解例子](https://www.cnblogs.com/acm-bingzi/p/javaAnnotation.html) diff --git a/Java基础教程/Java语言基础/06 异常处理.md b/Java基础教程/Java语言基础/06 异常处理.md deleted file mode 100644 index 156f4f8c..00000000 --- a/Java基础教程/Java语言基础/06 异常处理.md +++ /dev/null @@ -1,11 +0,0 @@ -## 八、异常 - -Throwable 可以用来表示任何可以作为异常抛出的类,分为两种: **Error** 和 **Exception**。其中 Error 用来表示 JVM 无法处理的错误,Exception 分为两种: - -- **受检异常** :需要用 try...catch... 语句捕获并进行处理,并且可以从异常中恢复; -- **非受检异常** :是程序运行时错误,例如除 0 会引发 Arithmetic Exception,此时程序崩溃并且无法恢复。 - -

- -- [Java 入门之异常处理](https://www.cnblogs.com/Blue-Keroro/p/8875898.html) -- [Java Exception Interview Questions and Answers](https://www.journaldev.com/2167/java-exception-interview-questions-and-answersl) diff --git a/Java基础教程/Java语言基础/06 接口和抽象类.md b/Java基础教程/Java语言基础/06 接口和抽象类.md new file mode 100644 index 00000000..27d18a1b --- /dev/null +++ b/Java基础教程/Java语言基础/06 接口和抽象类.md @@ -0,0 +1,97 @@ + +## 1 抽象类 + + +抽象类和抽象方法都使用 abstract 关键字进行声明。 +* 如果一个类中包含抽象方法,那么这个类必须声明为抽象类。 +* 任何子类必须重写父类的抽象方法,或者声明自身为抽象类。 + + +抽象类和普通类最大的区别是,抽象类不能被实例化,只能被继承。 + +```java +public abstract class AbstractClassExample { + + protected int x; + private int y; + + public abstract void func1(); + + public void func2() { + System.out.println("func2"); + } +} +``` + +```java +public class AbstractExtendClassExample extends AbstractClassExample { + @Override + public void func1() { + System.out.println("func1"); + } +} +``` + +## 2 接口 + + +implements关键字 +使用 implements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔) + + +接口是抽象类的延伸,在 Java 8 之前,它可以看成是一个完全抽象的类,也就是说它不能有任何的方法实现。 + +从 Java 8 开始,**接口也可以拥有默认的方法实现**,这是因为不支持默认方法的接口的维护成本太高了。在 Java 8 之前,如果一个接口想要添加新的方法,那么要修改所有实现了该接口的类,让它们都实现新增的方法。 + +接口的成员(字段 + 方法)默认都是 public 的,并且不允许定义为 private 或者 protected。从 Java 9 开始,**允许将方法定义为 private**,这样就能定义某些复用的代码又不会把方法暴露出去。 + +接口的字段默认都是 static 和 final 的。 + +```java +public interface InterfaceExample { + + void func1(); + + default void func2(){ + System.out.println("func2"); + } + + int x = 123; + // int y; // Variable 'y' might not have been initialized + public int z = 0; // Modifier 'public' is redundant for interface fields + // private int k = 0; // Modifier 'private' not allowed here + // protected int l = 0; // Modifier 'protected' not allowed here + // private void fun3(); // Modifier 'private' not allowed here +} +``` + +```java +public class InterfaceImplementExample implements InterfaceExample { + @Override + public void func1() { + System.out.println("func1"); + } +} +``` + + +### 抽象类和接口比较 + +- 从设计层面上看,抽象类提供了一种 IS-A 关系,需要满足里式替换原则,即子类对象必须能够替换掉所有父类对象。而接口更像是一种 LIKE-A 关系,它只是提供一种方法实现契约,并不要求接口和实现接口的类具有 IS-A 关系。 +- 从使用上来看,一个类可以实现多个接口,但是不能继承多个抽象类。 +- 接口的字段只能是 static 和 final 类型的,而抽象类的字段没有这种限制。 +- 接口的成员只能是 public 的,而抽象类的成员可以有多种访问权限。 + +### 抽象类和接口选择 +使用接口: + +- 需要让不相关的类都实现一个方法,例如不相关的类都可以实现 Comparable 接口中的 compareTo() 方法; +- 需要使用多重继承。 + +使用抽象类: + +- 需要在几个相关的类中共享代码。 +- 需要能控制继承来的成员的访问权限,而不是都为 public。 +- 需要继承非静态和非常量字段。 + +在很多情况下,接口优先于抽象类。因为接口没有抽象类严格的类层次结构要求,可以灵活地为一个类添加行为。并且从 Java 8 开始,接口也可以有默认的方法实现,使得修改接口的成本也变的很低。 diff --git a/Java基础教程/Java语言基础/07 异常处理.md b/Java基础教程/Java语言基础/07 异常处理.md new file mode 100644 index 00000000..a60e1a64 --- /dev/null +++ b/Java基础教程/Java语言基础/07 异常处理.md @@ -0,0 +1,332 @@ +## 1 异常概述 + +### 异常与错误 +异常是程序中的一些错误。 + +* 检查性异常:最具代表的检查性异常是用户错误或问题引起的异常,这是程序员无法预见的。例如要打开一个不存在文件时,一个异常就发生了,这些异常在编译时不能被简单地忽略。 +* 运行时异常:运行时异常是可能被程序员避免的异常。与检查性异常相反,运行时异常可以在编译时被忽略。 +* 错误:错误不是异常,而是脱离程序员控制的问题。错误在代码中通常被忽略。例如,当栈溢出时,一个错误就发生了,它们在编译也检查不到的。 + + +### 异常的产生 + +* 用户输入了非法数据。 +* 要打开的文件不存在。 +* 网络通信时连接中断 +* JVM内存溢出。 + + +### 异常的层次 + + + +Throwable 可以用来表示任何可以作为异常抛出的类,分为两种: **Error** 和 **Exception**。其中 Error 用来表示 JVM 无法处理的错误,Error 用来指示运行时环境发生的错误,程序不会从Error中恢复,而是直接down掉。Exception 分为两种: + +- **受检异常** :需要用 try...catch... 语句捕获并进行处理,并且可以从异常中恢复; +- **非受检异常** :是程序运行时错误,例如除 0 会引发 Arithmetic Exception,此时程序崩溃并且无法恢复。 + + + +![](image/2022-07-11-19-20-38.png) + + +## 2 异常使用 + +### 异常中的方法 + +* public String getMessage() +返回关于发生的异常的详细信息。这个消息在Throwable 类的构造函数中初始化了。 +* public Throwable getCause() +返回一个 Throwable 对象代表异常原因。 +* public String toString() +返回此 Throwable 的简短描述。 +* public void printStackTrace() +将此 Throwable 及其回溯打印到标准错误流。。 +* public StackTraceElement [] getStackTrace() +返回一个包含堆栈层次的数组。下标为0的元素代表栈顶,最后一个元素代表方法调用堆栈的栈底。 +* public Throwable fillInStackTrace() +用当前的调用栈层次填充Throwable 对象栈层次,添加到栈层次任何先前信息中。 + +### 捕获异常 +* 使用 try 和 catch 关键字可以捕获异常。 +* Catch 语句包含要捕获异常类型的声明。 +```java +try +{ + // 程序代码 +}catch(ExceptionName e1) +{ + //Catch 块 +} + +// 文件名 : ExcepTest.java +import java.io.*; +public class ExcepTest{ + + public static void main(String args[]){ + try{ + int a[] = new int[2]; + System.out.println("Access element three :" + a[3]); + }catch(ArrayIndexOutOfBoundsException e){ + System.out.println("Exception thrown :" + e); + } + System.out.println("Out of the block"); + } +} +``` + +### 多重捕获结构 + +* 没有发生异常,会通过所有的捕获语句,不会进入catch +* 发生异常,则进入捕获语句,并且不再执行其他捕获语句。执行完成后跳出try-catch语句块,然后执行后续内容。不会终端程序执行。 +```java +try{ + // 程序代码 +}catch(异常类型1 异常的变量名1){ + // 程序代码 +}catch(异常类型2 异常的变量名2){ + // 程序代码 +}catch(异常类型3 异常的变量名3){ + // 程序代码 +} +``` + +### throws/throw 抛出异常 +如果一个方法无法处理捕获到的异常,那么该方法必须使用 throws 关键字来声明。使用 throw 关键字抛出一个异常。 + +throws关键字用来声明该方法可能抛出的异常。只起到声明作用。 + +```java +import java.io.*; +public class className +{ + public void deposit(double amount) throws RemoteException + { + // Method implementation + throw new RemoteException(); + } + //Remainder of class definition +} +``` + +### finally关键字 + +无论是否发生异常,finally 代码块中的代码总会被执行。在 finally 代码块中,可以运行清理类型等收尾善后性质的语句。 + +> 即使之前的catch语句中有return语句。finally语句块仍旧会被执行。 + +```java +try{ + // 程序代码 +}catch(异常类型1 异常的变量名1){ + // 程序代码 +}catch(异常类型2 异常的变量名2){ + // 程序代码 +}finally{ + // 程序代码 +} + +public class ExcepTest{ + public static void main(String args[]){ + int a[] = new int[2]; + try{ + System.out.println("Access element three :" + a[3]); + }catch(ArrayIndexOutOfBoundsException e){ + System.out.println("Exception thrown :" + e); + } + finally{ + a[0] = 6; + System.out.println("First element value: " +a[0]); + System.out.println("The finally statement is executed"); + } + } +} +``` + + +### try-with-resources + +> 模仿python的with语句 + +JDK7 之后,Java 新增的 try-with-resource 语法糖来打开资源,并且可以在语句执行完毕后确保每个资源都被自动关闭 。 + +JDK7 之前所有被打开的系统资源,比如流、文件或者 Socket 连接等,都需要被开发者手动关闭,否则将会造成资源泄露。 +```java +import java.io.*; + +public class RunoobTest { + + public static void main(String[] args) { + String line; + try(BufferedReader br = new BufferedReader(new FileReader("test.txt"))) { + while ((line = br.readLine()) != null) { + System.out.println("Line =>"+line); + } + } catch (IOException e) { + System.out.println("IOException in try block =>" + e.getMessage()); + } + } +} +try (resource declaration) { + // 使用的资源 +} catch (ExceptionType e1) { + // 异常块 +} +``` + +* try with resource declaration可以同时处理多个打开的资源 +* 多个声明资源时,try-with-resources 语句以相反的顺序关闭这些资源。 +```java +import java.io.*; +import java.util.*; +class RunoobTest { + public static void main(String[] args) throws IOException{ + try (Scanner scanner = new Scanner(new File("testRead.txt")); + PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) { + while (scanner.hasNext()) { + writer.print(scanner.nextLine()); + } + } + } +} +``` +## 3 自定义异常 + +### 自定义异常 +* 所有异常都必须是 Throwable 的子类。 +* 如果希望写一个检查性异常类,则需要继承 Exception 类。 +* 如果你想写一个运行时异常类,那么需要继承 RuntimeException 类。 + +```java +class MyException extends Exception{ +} + +// 文件名InsufficientFundsException.java +import java.io.*; + +//自定义异常类,继承Exception类 +public class InsufficientFundsException extends Exception +{ + //此处的amount用来储存当出现异常(取出钱多于余额时)所缺乏的钱 + private double amount; + public InsufficientFundsException(double amount) + { + this.amount = amount; + } + public double getAmount() + { + return amount; + } +} +``` + +### 使用自定义的异常 + +```java +/ 文件名称 CheckingAccount.java +import java.io.*; + +//此类模拟银行账户 +public class CheckingAccount +{ + //balance为余额,number为卡号 + private double balance; + private int number; + public CheckingAccount(int number) + { + this.number = number; + } + //方法:存钱 + public void deposit(double amount) + { + balance += amount; + } + //方法:取钱 + public void withdraw(double amount) throws + InsufficientFundsException + { + if(amount <= balance) + { + balance -= amount; + } + else + { + double needs = amount - balance; + throw new InsufficientFundsException(needs); + } + } + //方法:返回余额 + public double getBalance() + { + return balance; + } + //方法:返回卡号 + public int getNumber() + { + return number; + } +} +``` + +### 处理自定义的异常 + +``` +//文件名称 BankDemo.java +public class BankDemo +{ + public static void main(String [] args) + { + CheckingAccount c = new CheckingAccount(101); + System.out.println("Depositing $500..."); + c.deposit(500.00); + try + { + System.out.println("\nWithdrawing $100..."); + c.withdraw(100.00); + System.out.println("\nWithdrawing $600..."); + c.withdraw(600.00); + }catch(InsufficientFundsException e) + { + System.out.println("Sorry, but you are short $" + + e.getAmount()); + e.printStackTrace(); + } + } +} +``` + + +## 4 常见的异常 + +### 常见的运行时异常 + +| 异常 | 描述 | +|---------------------------------|------------------------------------------------------------------| +| ArithmeticException | 当出现异常的运算条件时,抛出此异常。例如,一个整数"除以零"时,抛出此类的一个实例。 | +| ArrayIndexOutOfBoundsException | 用非法索引访问数组时抛出的异常。如果索引为负或大于等于数组大小,则该索引为非法索引。 | +| ArrayStoreException | 试图将错误类型的对象存储到一个对象数组时抛出的异常。 | +| ClassCastException | 当试图将对象强制转换为不是实例的子类时,抛出该异常。 | +| IllegalArgumentException | 抛出的异常表明向方法传递了一个不合法或不正确的参数。 | +| IllegalMonitorStateException | 抛出的异常表明某一线程已经试图等待对象的监视器,或者试图通知其他正在等待对象的监视器而本身没有指定监视器的线程。 | +| IllegalStateException | 在非法或不适当的时间调用方法时产生的信号。换句话说,即 Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。 | +| IllegalThreadStateException | 线程没有处于请求操作所要求的适当状态时抛出的异常。 | +| IndexOutOfBoundsException | 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出。 | +| NegativeArraySizeException | 如果应用程序试图创建大小为负的数组,则抛出该异常。 | +| NullPointerException | 当应用程序试图在需要对象的地方使用 null 时,抛出该异常 | +| NumberFormatException | 当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当格式时,抛出该异常。 | +| SecurityException | 由安全管理器抛出的异常,指示存在安全侵犯。 | +| StringIndexOutOfBoundsException | 此异常由 String 方法抛出,指示索引或者为负,或者超出字符串的大小。 | +| UnsupportedOperationException | 当不支持请求的操作时,抛出该异常。 | + + +### 常见的检查性异常 + +| 异常 | 描述 | +|----------------------------|----------------------------------------------------------------------------| +| ClassNotFoundException | 应用程序试图加载类时,找不到相应的类,抛出该异常。 | +| CloneNotSupportedException | 当调用 Object 类中的 clone 方法克隆对象,但该对象的类无法实现 Cloneable 接口时,抛出该异常。 | +| IllegalAccessException | 拒绝访问一个类的时候,抛出该异常。 | +| InstantiationException | 当试图使用 Class 类中的 newInstance 方法创建一个类的实例,而指定的类对象因为是一个接口或是一个抽象类而无法实例化时,抛出该异常。 | +| InterruptedException | 一个线程被另一个线程中断,抛出该异常。 | +| NoSuchFieldException | 请求的变量不存在 | +| NoSuchMethodException | 请求的方法不存在 | diff --git a/Java基础教程/Java语言基础/08 Java反射.md b/Java基础教程/Java语言基础/08 Java反射.md new file mode 100644 index 00000000..aba00890 --- /dev/null +++ b/Java基础教程/Java语言基础/08 Java反射.md @@ -0,0 +1,381 @@ + +- [深入解析 Java 反射(1)- 基础](http://www.sczyh30.com/posts/Java/java-reflection-1/) +- [Java反射超详细,一个快乐的野指针](https://blog.csdn.net/qq_44715943/article/details/120587716) +## 1 反射概述 + +### 反射机制的作用 +* 通过java语言中的反射机制可以操作字节码文件(可以读和修改字节码文件。) +* 通过反射机制可以操作代码片段。(class文件。) + + +### Class对象 + +Class对象的作用 +* 每个类都有一个**Class**对象,包含了与类有关的信息,代表整个字节码。代表一个类型,代表整个类。。当编译一个新类时,会产生一个同名的 .class 文件,该文件内容保存着 Class 对象。 + +* 类加载相当于 Class 对象的加载,类在第一次使用时才动态加载到 JVM 中。也可以使用 `Class.forName("com.mysql.jdbc.Driver")` 这种方式来控制类的加载,该方法会返回一个 Class 对象。 + +* 反射可以提供运行时的类信息,并且这个类可以在运行时才加载进来,甚至在编译时期该类的 .class 不存在也可以加载进来。 + +获取Class对象的方法 + +* Class.forName(“完整类名带包名”) 静态方法 +* 对象.getClass() +* 任何类型.class + + +### 反射机制的使用 + +java.lang.reflect.*;存储与反射相关的类 + +| 类 | 含义 | +|------------------|-----| +| java.lang.Class | 代表整个字节码。代表一个类型,代表整个类。 | +| java.lang.reflect.Method | 代表字节码中的方法字节码。代表类中的方法。 | +| java.lang.reflect.Constructor | 代表字节码中的构造方法字节码。代表类中的构造方法。 | +| java.lang.reflect.Field | 代表字节码中的属性字节码。代表类中的成员变量(静态变量+实例变量)。 | + + + + +Class 和 java.lang.reflect.* 一起对反射提供了支持,java.lang.reflect 类库主要包含了以下三个类: + +- **Field** :可以使用 get() 和 set() 方法读取和修改 Field 对象关联的字段; +- **Method** :可以使用 invoke() 方法调用与 Method 对象关联的方法; +- **Constructor** :可以用 Constructor 的 newInstance() 创建新的对象。 + +### 反射机制的优点 + +- **可扩展性** :应用程序可以利用全限定名创建可扩展对象的实例,来使用来自外部的用户自定义类。 +- **类浏览器和可视化开发环境** :一个类浏览器需要可以枚举类的成员。可视化开发环境(如 IDE)可以从利用反射中可用的类型信息中受益,以帮助程序员编写正确的代码。 +- **调试器和测试工具** : 调试器需要能够检查一个类里的私有成员。测试工具可以利用反射来自动地调用类里定义的可被发现的 API 定义,以确保一组测试中有较高的代码覆盖率。 + +### 反射的缺点 + +尽管反射非常强大,但也不能滥用。如果一个功能可以不用反射完成,那么最好就不用。在我们使用反射技术时,下面几条内容应该牢记于心。 + +- **性能开销** :反射涉及了动态类型的解析,所以 JVM 无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被执行的代码或对性能要求很高的程序中使用反射。 + +- **安全限制** :使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行,如 Applet,那么这就是个问题了。 + +- **内部暴露** :由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用,这可能导致代码功能失调并破坏可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化。 + + + + +### 反射机制的使用 + +* 使用Class实例化一个对象。 +```java +class ReflectTest02{ + public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { + // 下面这段代码是以反射机制的方式创建对象。 + + // 通过反射机制,获取Class,通过Class来实例化对象 + Class c = Class.forName("javase.reflectBean.User"); + // newInstance() 这个方法会调用User这个类的无参数构造方法,完成对象的创建。 + // 重点是:newInstance()调用的是无参构造,必须保证无参构造是存在的! + Object obj = c.newInstance(); + System.out.println(obj); + } +} +``` + + +* 使得一个类的静态代码执行,而其他代码不执行。例如JDBC中不需要创建实例而知识执行静态方法.这个方法的执行会导致类加载,类加载时,静态代码块执行。 + +```java +Class.forName("完整类名"); +``` + +## 2 反射机制实现 +### Class 中的方法 +| 方法名 | 备注 | +|---|---| +| public T newInstance() | 创建对象 | +| public String getName() | 返回完整类名带包名 | +| public String getSimpleName() | 返回类名 | +| public Field[] getFields() | 返回类中public修饰的属性 | +| public Field[] getDeclaredFields() | 返回类中所有的属性 | +| public Field getDeclaredField(String name) | 根据属性名name获取指定的属性 | +| public native int getModifiers() | 获取属性的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号【一般配合Modifier类的toString(int x)方法使用】 | +| public Method[] getDeclaredMethods() | 返回类中所有的实例方法 | +| public Method getDeclaredMethod(String name, Class<?>… parameterTypes) | 根据方法名name和方法形参获取指定方法 | +| public Constructor<?>[] getDeclaredConstructors() | 返回类中所有的构造方法 | +| public Constructor getDeclaredConstructor(Class<?>… parameterTypes) | 根据方法形参获取指定的构造方法 | +| ---- | ---- | +| public native Class<? super T> getSuperclass() | 返回调用类的父类 | +| public Class<?>[] getInterfaces() | 返回调用类实现的接口集合 | + + +### Field中的方法 + +| 方法名 | 备注 | +|---|---| +| public String getName() | 返回属性名 | +| public int getModifiers() | 获取属性的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号【一般配合Modifier类的toString(int x)方法使用】 | +| public Class<?> getType() | 以Class类型,返回属性类型【一般配合Class类的getSimpleName()方法使用】 | +| public void set(Object obj, Object value) | 设置属性值 | +| public Object get(Object obj) | 读取属性值 | + + +```java +/* +必须掌握: + 怎么通过反射机制访问一个java对象的属性? + 给属性赋值set + 获取属性的值get + */ +class ReflectTest07{ + public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException { + //不使用反射机制给属性赋值 + Student student = new Student(); + /**给属性赋值三要素:给s对象的no属性赋值1111 + * 要素1:对象s + * 要素2:no属性 + * 要素3:1111 + */ + student.no = 1111; + /**读属性值两个要素:获取s对象的no属性的值。 + * 要素1:对象s + * 要素2:no属性 + */ + System.out.println(student.no); + + //使用反射机制给属性赋值 + Class studentClass = Class.forName("javase.reflectBean.Student"); + Object obj = studentClass.newInstance();// obj就是Student对象。(底层调用无参数构造方法) + + // 获取no属性(根据属性的名称来获取Field) + Field noField = studentClass.getDeclaredField("no"); + // 给obj对象(Student对象)的no属性赋值 + /* + 虽然使用了反射机制,但是三要素还是缺一不可: + 要素1:obj对象 + 要素2:no属性 + 要素3:22222值 + 注意:反射机制让代码复杂了,但是为了一个“灵活”,这也是值得的。 + */ + noField.set(obj, 22222); + + // 读取属性的值 + // 两个要素:获取obj对象的no属性的值。 + System.out.println(noField.get(obj)); + } +``` + +* set()方法不可以访问私有属性,需要打破封装,才可以。 +* public void setAccessible(boolean flag) 默认false,设置为true为打破封装 +```java + // 可以访问私有的属性吗? + Field nameField = studentClass.getDeclaredField("name"); + // 打破封装(反射机制的缺点:打破封装,可能会给不法分子留下机会!!!) + // 这样设置完之后,在外部也是可以访问private的。 + nameField.setAccessible(true); + // 给name属性赋值 + nameField.set(obj, "xiaowu"); + // 获取name属性的值 + System.out.println(nameField.get(obj)); +``` + + +### Method中的方法 + +| 方法名 | 备注 | +|---|---| +| public String getName() | 返回方法名 | +| public int getModifiers() | 获取方法的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号【一般配合Modifier类的toString(int x)方法使用】 | +| public Class<?> getReturnType() | 以Class类型,返回方法类型【一般配合Class类的getSimpleName()方法使用】 | +| public Class<?>[] getParameterTypes() | 返回方法的修饰符列表(一个方法的参数可能会有多个。)【结果集一般配合Class类的getSimpleName()方法使用】 | +| public Object invoke(Object obj, Object… args) | 调用方法 | + +* 获取一个类中的method方法 +```java +/* +了解一下,不需要掌握(反编译一个类的方法。) + */ +class ReflectTest09{ + public static void main(String[] args) throws ClassNotFoundException { + StringBuilder s = new StringBuilder(); + + Class userServiceClass = Class.forName("java.lang.String"); + + s.append(Modifier.toString(userServiceClass.getModifiers())); + s.append(" class "); + s.append(userServiceClass.getSimpleName()); + s.append(" {\n"); + + // 获取所有的Method(包括私有的!) + Method[] methods = userServiceClass.getDeclaredMethods(); + for (Method m : methods){ + s.append("\t"); + // 获取修饰符列表 + s.append(Modifier.toString(m.getModifiers())); + s.append(" "); + // 获取方法的返回值类型 + s.append(m.getReturnType().getSimpleName()); + s.append(" "); + // 获取方法名 + s.append(m.getName()); + s.append("("); + // 方法的修饰符列表(一个方法的参数可能会有多个。) + Class[] parameterTypes = m.getParameterTypes(); + for (int i = 0; i < parameterTypes.length; i++){ + s.append(parameterTypes[i].getSimpleName()); + if (i != parameterTypes.length - 1) s.append(", "); + } + s.append(") {}\n"); + } + s.append("}"); + System.out.println(s); + } +} +``` + + +* 调用类中的方法Method +* 方法.invoke(对象, 实参); + +```java +/* +重点:必须掌握,通过反射机制怎么调用一个对象的方法? + 五颗星***** + + 反射机制,让代码很具有通用性,可变化的内容都是写到配置文件当中, + 将来修改配置文件之后,创建的对象不一样了,调用的方法也不同了, + 但是java代码不需要做任何改动。这就是反射机制的魅力。 + */ +class ReflectTest10{ + public static void main(String[] args) throws Exception { + // 不使用反射机制,怎么调用方法 + // 创建对象 + UserService userService = new UserService(); + // 调用方法 + /* + 要素分析: + 要素1:对象userService + 要素2:login方法名 + 要素3:实参列表 + 要素4:返回值 + */ + System.out.println(userService.login("admin", "123") ? "登入成功!" : "登入失败!"); + + //使用反射机制调用方法 + Class userServiceClass = Class.forName("javase.reflectBean.UserService"); + // 创建对象 + Object obj = userServiceClass.newInstance(); + // 获取Method + Method loginMethod = userServiceClass.getDeclaredMethod("login", String.class, String.class); +// Method loginMethod = userServiceClass.getDeclaredMethod("login");//注:没有形参就不传 + // 调用方法 + // 调用方法有几个要素? 也需要4要素。 + // 反射机制中最最最最最重要的一个方法,必须记住。 + /* + 四要素: + loginMethod方法 + obj对象 + "admin","123" 实参 + retValue 返回值 + */ + Object resValues = loginMethod.invoke(obj, "admin", "123");//注:方法返回值是void 结果是null + System.out.println(resValues); + } +} +``` + + +### Constructor中的方法 + +| 方法名 | 备注 | +|---|---| +| public String getName() | 返回构造方法名 | +| public int getModifiers() | 获取构造方法的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号【一般配合Modifier类的toString(int x)方法使用】 | +| public Class<?>[] getParameterTypes() | 返回构造方法的修饰符列表(一个方法的参数可能会有多个。)【结果集一般配合Class类的getSimpleName()方法使用】 | +| public T newInstance(Object … initargs) | 创建对象【参数为创建对象的数据】 | + + +* 获取Constructor方法 + +```java +/* +反编译一个类的Constructor构造方法。 + */ +class ReflectTest11{ + public static void main(String[] args) throws ClassNotFoundException { + StringBuilder s = new StringBuilder(); + + Class vipClass = Class.forName("javase.reflectBean.Vip"); + + //public class UserService { + s.append(Modifier.toString(vipClass.getModifiers())); + s.append(" class "); + s.append(vipClass.getSimpleName()); + s.append("{\n"); + + Constructor[] constructors = vipClass.getDeclaredConstructors(); + for (Constructor c : constructors){ + //public Vip(int no, String name, String birth, boolean sex) { + s.append("\t"); + s.append(Modifier.toString(c.getModifiers())); + s.append(" "); +// s.append(c.getName());//包名+类名 + s.append(vipClass.getSimpleName());//类名 + s.append("("); + Class[] parameterTypes = c.getParameterTypes(); + for (int i = 0; i < parameterTypes.length; i++){ + s.append(parameterTypes[i].getSimpleName()); + if (i != parameterTypes.length - 1 ) s.append(", "); + } + s.append("){}\n"); + } + + s.append("}"); + System.out.println(s); + } +} +``` + +* 调用Constructor方法创建对象 + * 先获取到这个有参数的构造方法【用ClassgetDeclaredConstructor()方法获取】 + * 调用构造方法new对象【用Constructor类的newInstance()方法new对象】 + +```java +/* +比上一个例子(ReflectTest11)重要一些!!! + +通过反射机制调用构造方法实例化java对象。(这个不是重点) + */ +class ReflectTest12{ + public static void main(String[] args) throws Exception { + //不适用反射创建对象 + Vip vip1 = new Vip(); + Vip vip2 = new Vip(123, "zhangsan", "2001-10-19", false); + + //使用反射机制创建对象(以前) + Class vipClass = Class.forName("javase.reflectBean.Vip"); + // 调用无参数构造方法 + Object obj1 = vipClass.newInstance();//Class类的newInstance方法 + System.out.println(obj1); + + //使用反射机制创建对象(现在) + // 调用有参数的构造方法怎么办? + // 第一步:先获取到这个有参数的构造方法 + Constructor c1 = vipClass.getDeclaredConstructor(int.class, String.class, String.class, boolean.class); + // 第二步:调用构造方法new对象 + Object obj2 = c1.newInstance(321, "lsi", "1999-10-11", true);//Constructor类的newInstance方法 + System.out.println(obj2); + + // 获取无参数构造方法 + Constructor c2 = vipClass.getDeclaredConstructor(); + Object obj3 = c2.newInstance(); + System.out.println(obj3); + } +} +``` + + +### 获取一个类的父类以及实现的接口 +两个方法【Class类中的】 + +* public native Class getSuperclass() +* public Class[] getInterfaces() \ No newline at end of file diff --git a/Java基础教程/Java语言基础/09 Java泛型.md b/Java基础教程/Java语言基础/09 Java泛型.md new file mode 100644 index 00000000..474d50fd --- /dev/null +++ b/Java基础教程/Java语言基础/09 Java泛型.md @@ -0,0 +1,212 @@ +> [Java 泛型详解](https://blog.csdn.net/ChenRui_yz/article/details/122935621) +## 1 泛型概述 + +### 基本概念 + +Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。 + +泛型的本质是参数化类型,即给类型指定一个参数,然后在使用时再指定此参数具体的值,那样这个类型就可以在使用时决定了。这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。 + +![](image/2022-07-11-22-24-04.png) + + +### 泛型的基本用法 + +```java +public class Box { + // T stands for "Type" + private T t; + public void set(T t) { this.t = t; } + public T get() { return t; } +} +``` + +## 2 优势 +1. 安全性? +2. 消除转换? +3. 提升性能? +4. 重用行。不同类型不需要重载。泛型本质上也是一种编译时多态。 + +### 安全性 +在没有泛型之前,从集合中读取到的每一个对象都必须进行类型转换,如果不小心插入了错误的类型对象,在运行时的转换处理就会出错。 + +* 没有泛型的情况下使用集合: +```java +public static void noGeneric() { +ArrayList names = new ArrayList(); +names.add("mikechen的互联网架构"); +names.add(123); //编译正常 +} +``` +* 有泛型的情况下使用集合: +```java +public static void useGeneric() { +ArrayList names = new ArrayList<>(); +names.add("mikechen的互联网架构"); +names.add(123); //编译不通过 +} +``` +相当于告诉编译器每个集合接收的对象类型是什么,编译器在编译期就会做类型检查,告知是否插入了错误类型的对象,使得程序更加安全,增强了程序的健壮性。 + + +### 消除强制转换 +泛型的一个附带好处是,消除源代码中的许多强制类型转换,这使得代码更加可读,并且减少了出错机会。 + + +* 以下没有泛型的代码段需要强制转换: +```java +List list = new ArrayList(); +list.add("hello"); +String s = (String) list.get(0); +``` +* 当重写为使用泛型时,代码不需要强制转换: +```java +List list = new ArrayList(); +list.add("hello"); +String s = list.get(0); // no cast +``` + +- [Java 泛型详解](https://www.cnblogs.com/Blue-Keroro/p/8875898.html) +- [10 道 Java 泛型面试题](https://cloud.tencent.com/developer/article/1033693) + +### 避免了不必要的装箱、拆箱操作,提高程序的性能 + +在非泛型编程中,将简单类型作为Object传递时会引起Boxing(装箱)和Unboxing(拆箱)操作,这两个过程都是具有很大开销的。引入泛型后,就不必进行Boxing和Unboxing操作了,所以运行效率相对较高,特别在对集合操作非常频繁的系统中,这个特点带来的性能提升更加明显。 + +* 泛型变量固定了类型,使用的时候就已经知道是值类型还是引用类型,避免了不必要的装箱、拆箱操作。 +```java +object a=1;//由于是object类型,会自动进行装箱操作。 + +int b=(int)a;//强制转换,拆箱操作。这样一去一来,当次数多了以后会影响程序的运行效率。 +``` +* 使用泛型之后 +```java +public static T GetValue(T a) + +{ +  return a; +} + +public static void Main() + +{ +  int b=GetValue(1);//使用这个方法的时候已经指定了类型是int,所以不会有装箱和拆箱的操作。 +} +``` + +### 提高了代码的重用行 +> 省略 + +## 3 泛型的使用 + +### 泛型类 +* 定义泛型类,在类名后添加一对尖括号,并在尖括号中填写类型参数,参数可以有多个,多个参数使用逗号分隔: +```java +public class 类名 <泛型类型1,...> {} +public class GenericClass {} +``` + +* 实例代码 + +```java +public class GenericClass { + private T value; + + + public GenericClass(T value) { + this.value = value; + } + public T getValue() { + return value; + } + public void setValue(T value) { + this.value = value; + } +} +``` +### 泛型接口 + +```java +public interface GenericInterface { +void show(T value); +} + +public class StringShowImpl implements GenericInterface { +@Override +public void show(String value) { +System.out.println(value); +}} + +public class NumberShowImpl implements GenericInterface { +@Override +public void show(Integer value) { +System.out.println(value); +}} +``` + + +### 泛型方法 + +```java +修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ } + +/** +* +* @param t 传入泛型的参数 +* @param 泛型的类型 +* @return T 返回值为T类型 +* 说明: +* 1)public 与 返回值中间非常重要,可以理解为声明此方法为泛型方法。 +* 2)只有声明了的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。 +* 3)表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。 +* 4)与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E等形式的参数常用于表示泛型。 +*/ +public T genercMethod(T t){ +System.out.println(t.getClass()); +System.out.println(t); +return t; +} +``` + +## 4 泛型通配符 + +Java泛型的通配符是用于解决泛型之间引用传递问题的特殊语法。泛型与继承之间的关系 +1. 无边界通配符 + 1. 无边界的通配符的主要作用就是让泛型能够接受未知类型的数据. +2. 固定上边界的通配符 + 1. 使用固定上边界的通配符的泛型, 就能够接受指定类及其子类类型的数据。 + 2. 要声明使用该类通配符, 采用的形式, 这里的E就是该泛型的上边界。 + 3. 注意: 这里虽然用的是extends关键字, 却不仅限于继承了父类E的子类, 也可以代指显现了接口E的类 +3. 固定下边界的通配符 + 1. 使用固定下边界的通配符的泛型, 就能够接受指定类及其父类类型的数据.。 + 2. 要声明使用该类通配符, 采用的形式, 这里的E就是该泛型的下边界.。 + 3. 注意: 你可以为一个泛型指定上边界或下边界, 但是不能同时指定上下边界。 +```java +//表示类型参数可以是任何类型 +public class Apple{} + +//表示类型参数必须是A或者是A的子类 +public class Apple{} + +//表示类型参数必须是A或者是A的超类型 +public class Apple{} +``` + +## 5 泛型中的KTVE + +泛型中的规范 +* T:任意类型 type +* E:集合中元素的类型 element +* K:key-value形式 key +* V: key-value形式 value +* N: Number(数值类型) +* ?: 表示不确定的java类型 + + +## 6 泛型的实现原理 + +泛型本质是将数据类型参数化,它通过擦除的方式来实现,即编译器会在编译期间「擦除」泛型语法并相应的做出一些类型转换动作。 + +实际上编译器会正常的将使用泛型的地方编译并进行类型擦除,然后返回实例。但是除此之外的是,如果构建泛型实例时使用了泛型语法,那么编译器将标记该实例并关注该实例后续所有方法的调用,每次调用前都进行安全检查,非指定类型的方法都不能调用成功。 + +实际上编译器不仅关注一个泛型方法的调用,它还会为某些返回值为限定的泛型类型的方法进行强制类型转换,由于类型擦除,返回值为泛型类型的方法都会擦除成 Object 类型,当这些方法被调用后,编译器会额外插入一行 checkcast 指令用于强制类型转换,这一个过程就叫做『泛型翻译』。 \ No newline at end of file diff --git a/Java基础教程/Java语言基础/10 Java注解.md b/Java基础教程/Java语言基础/10 Java注解.md new file mode 100644 index 00000000..045c76a0 --- /dev/null +++ b/Java基础教程/Java语言基础/10 Java注解.md @@ -0,0 +1,5 @@ +## 10 注解 + +Java 注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。 + +[注解 Annotation 实现原理与自定义注解例子](https://www.cnblogs.com/acm-bingzi/p/javaAnnotation.html) diff --git a/Java基础教程/Java语言基础/11 Object类.md b/Java基础教程/Java语言基础/11 Object类.md new file mode 100644 index 00000000..1989fd78 --- /dev/null +++ b/Java基础教程/Java语言基础/11 Object类.md @@ -0,0 +1,366 @@ +## Object 通用方法 + +### 概览 + +```java + +public native int hashCode() + +public boolean equals(Object obj) + +protected native Object clone() throws CloneNotSupportedException + +public String toString() + +public final native Class getClass() + +protected void finalize() throws Throwable {} + +public final native void notify() + +public final native void notifyAll() + +public final native void wait(long timeout) throws InterruptedException + +public final void wait(long timeout, int nanos) throws InterruptedException + +public final void wait() throws InterruptedException +``` + +### equals() + +**1. 等价关系** + +两个对象具有等价关系,需要满足以下五个条件: + +Ⅰ 自反性 + +```java +x.equals(x); // true +``` + +Ⅱ 对称性 + +```java +x.equals(y) == y.equals(x); // true +``` + +Ⅲ 传递性 + +```java +if (x.equals(y) && y.equals(z)) + x.equals(z); // true; +``` + +Ⅳ 一致性 + +多次调用 equals() 方法结果不变 + +```java +x.equals(y) == x.equals(y); // true +``` + +Ⅴ 与 null 的比较 + +对任何不是 null 的对象 x 调用 x.equals(null) 结果都为 false + +```java +x.equals(null); // false; +``` + +**2. 等价与相等** + +- 对于基本类型,== 判断两个值是否相等,基本类型没有 equals() 方法。 +- 对于引用类型,== 判断两个变量是否引用同一个对象,而 equals() 判断引用的对象是否等价。 + +```java +Integer x = new Integer(1); +Integer y = new Integer(1); +System.out.println(x.equals(y)); // true +System.out.println(x == y); // false +``` + +**3. 实现** + +- 检查是否为同一个对象的引用,如果是直接返回 true; +- 检查是否是同一个类型,如果不是,直接返回 false; +- 将 Object 对象进行转型; +- 判断每个关键域是否相等。 + +```java +public class EqualExample { + + private int x; + private int y; + private int z; + + public EqualExample(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + EqualExample that = (EqualExample) o; + + if (x != that.x) return false; + if (y != that.y) return false; + return z == that.z; + } +} +``` + +### hashCode() + +hashCode() 返回哈希值,而 equals() 是用来判断两个对象是否等价。等价的两个对象散列值一定相同,但是散列值相同的两个对象不一定等价,这是因为计算哈希值具有随机性,两个值不同的对象可能计算出相同的哈希值。 + +在覆盖 equals() 方法时应当总是覆盖 hashCode() 方法,保证等价的两个对象哈希值也相等。 + +HashSet 和 HashMap 等集合类使用了 hashCode() 方法来计算对象应该存储的位置,因此要将对象添加到这些集合类中,需要让对应的类实现 hashCode() 方法。 + +下面的代码中,新建了两个等价的对象,并将它们添加到 HashSet 中。我们希望将这两个对象当成一样的,只在集合中添加一个对象。但是 EqualExample 没有实现 hashCode() 方法,因此这两个对象的哈希值是不同的,最终导致集合添加了两个等价的对象。 + +```java +EqualExample e1 = new EqualExample(1, 1, 1); +EqualExample e2 = new EqualExample(1, 1, 1); +System.out.println(e1.equals(e2)); // true +HashSet set = new HashSet<>(); +set.add(e1); +set.add(e2); +System.out.println(set.size()); // 2 +``` + +理想的哈希函数应当具有均匀性,即不相等的对象应当均匀分布到所有可能的哈希值上。这就要求了哈希函数要把所有域的值都考虑进来。可以将每个域都当成 R 进制的某一位,然后组成一个 R 进制的整数。 + +R 一般取 31,因为它是一个奇素数,如果是偶数的话,当出现乘法溢出,信息就会丢失,因为与 2 相乘相当于向左移一位,最左边的位丢失。并且一个数与 31 相乘可以转换成移位和减法:`31*x == (x<<5)-x`,编译器会自动进行这个优化。 + +```java +@Override +public int hashCode() { + int result = 17; + result = 31 * result + x; + result = 31 * result + y; + result = 31 * result + z; + return result; +} +``` + +### toString() + +默认返回 ToStringExample@4554617c 这种形式,其中 @ 后面的数值为散列码的无符号十六进制表示。 + +```java +public class ToStringExample { + + private int number; + + public ToStringExample(int number) { + this.number = number; + } +} +``` + +```java +ToStringExample example = new ToStringExample(123); +System.out.println(example.toString()); +``` + +```html +ToStringExample@4554617c +``` + +### clone() + +**1. cloneable** + +clone() 是 Object 的 protected 方法,它不是 public,一个类不显式去重写 clone(),其它类就不能直接去调用该类实例的 clone() 方法。 + +```java +public class CloneExample { + private int a; + private int b; +} +``` + +```java +CloneExample e1 = new CloneExample(); +// CloneExample e2 = e1.clone(); // 'clone()' has protected access in 'java.lang.Object' +``` + +重写 clone() 得到以下实现: + +```java +public class CloneExample { + private int a; + private int b; + + @Override + public CloneExample clone() throws CloneNotSupportedException { + return (CloneExample)super.clone(); + } +} +``` + +```java +CloneExample e1 = new CloneExample(); +try { + CloneExample e2 = e1.clone(); +} catch (CloneNotSupportedException e) { + e.printStackTrace(); +} +``` + +```html +java.lang.CloneNotSupportedException: CloneExample +``` + +以上抛出了 CloneNotSupportedException,这是因为 CloneExample 没有实现 Cloneable 接口。 + +应该注意的是,clone() 方法并不是 Cloneable 接口的方法,而是 Object 的一个 protected 方法。Cloneable 接口只是规定,如果一个类没有实现 Cloneable 接口又调用了 clone() 方法,就会抛出 CloneNotSupportedException。 + +```java +public class CloneExample implements Cloneable { + private int a; + private int b; + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } +} +``` + +**2. 浅拷贝** + +拷贝对象和原始对象的引用类型引用同一个对象。 + +```java +public class ShallowCloneExample implements Cloneable { + + private int[] arr; + + public ShallowCloneExample() { + arr = new int[10]; + for (int i = 0; i < arr.length; i++) { + arr[i] = i; + } + } + + public void set(int index, int value) { + arr[index] = value; + } + + public int get(int index) { + return arr[index]; + } + + @Override + protected ShallowCloneExample clone() throws CloneNotSupportedException { + return (ShallowCloneExample) super.clone(); + } +} +``` + +```java +ShallowCloneExample e1 = new ShallowCloneExample(); +ShallowCloneExample e2 = null; +try { + e2 = e1.clone(); +} catch (CloneNotSupportedException e) { + e.printStackTrace(); +} +e1.set(2, 222); +System.out.println(e2.get(2)); // 222 +``` + +**3. 深拷贝** + +拷贝对象和原始对象的引用类型引用不同对象。 + +```java +public class DeepCloneExample implements Cloneable { + + private int[] arr; + + public DeepCloneExample() { + arr = new int[10]; + for (int i = 0; i < arr.length; i++) { + arr[i] = i; + } + } + + public void set(int index, int value) { + arr[index] = value; + } + + public int get(int index) { + return arr[index]; + } + + @Override + protected DeepCloneExample clone() throws CloneNotSupportedException { + DeepCloneExample result = (DeepCloneExample) super.clone(); + result.arr = new int[arr.length]; + for (int i = 0; i < arr.length; i++) { + result.arr[i] = arr[i]; + } + return result; + } +} +``` + +```java +DeepCloneExample e1 = new DeepCloneExample(); +DeepCloneExample e2 = null; +try { + e2 = e1.clone(); +} catch (CloneNotSupportedException e) { + e.printStackTrace(); +} +e1.set(2, 222); +System.out.println(e2.get(2)); // 2 +``` + +**4. clone() 的替代方案** + +使用 clone() 方法来拷贝一个对象即复杂又有风险,它会抛出异常,并且还需要类型转换。Effective Java 书上讲到,最好不要去使用 clone(),可以使用拷贝构造函数或者拷贝工厂来拷贝一个对象。 + +```java +public class CloneConstructorExample { + + private int[] arr; + + public CloneConstructorExample() { + arr = new int[10]; + for (int i = 0; i < arr.length; i++) { + arr[i] = i; + } + } + + public CloneConstructorExample(CloneConstructorExample original) { + arr = new int[original.arr.length]; + for (int i = 0; i < original.arr.length; i++) { + arr[i] = original.arr[i]; + } + } + + public void set(int index, int value) { + arr[index] = value; + } + + public int get(int index) { + return arr[index]; + } +} +``` + +```java +CloneConstructorExample e1 = new CloneConstructorExample(); +CloneConstructorExample e2 = new CloneConstructorExample(e1); +e1.set(2, 222); +System.out.println(e2.get(2)); // 2 +``` diff --git a/Java基础教程/Java语言基础/10 包装器类.md b/Java基础教程/Java语言基础/12 包装器类.md similarity index 100% rename from Java基础教程/Java语言基础/10 包装器类.md rename to Java基础教程/Java语言基础/12 包装器类.md diff --git a/Java基础教程/Java语言基础/11 String&StringBuffer类.md b/Java基础教程/Java语言基础/13 String&StringBuffer类.md similarity index 100% rename from Java基础教程/Java语言基础/11 String&StringBuffer类.md rename to Java基础教程/Java语言基础/13 String&StringBuffer类.md diff --git a/Java基础教程/Java语言基础/12 Number&Math类.md b/Java基础教程/Java语言基础/14 Number&Math类.md similarity index 100% rename from Java基础教程/Java语言基础/12 Number&Math类.md rename to Java基础教程/Java语言基础/14 Number&Math类.md diff --git a/Java基础教程/Java语言基础/image/2022-07-11-15-48-30.png b/Java基础教程/Java语言基础/image/2022-07-11-15-48-30.png new file mode 100644 index 00000000..c7f5567a Binary files /dev/null and b/Java基础教程/Java语言基础/image/2022-07-11-15-48-30.png differ diff --git a/Java基础教程/Java语言基础/image/2022-07-11-17-17-10.png b/Java基础教程/Java语言基础/image/2022-07-11-17-17-10.png new file mode 100644 index 00000000..2bd76677 Binary files /dev/null and b/Java基础教程/Java语言基础/image/2022-07-11-17-17-10.png differ diff --git a/Java基础教程/Java语言基础/image/2022-07-11-19-20-38.png b/Java基础教程/Java语言基础/image/2022-07-11-19-20-38.png new file mode 100644 index 00000000..0c6bcb0c Binary files /dev/null and b/Java基础教程/Java语言基础/image/2022-07-11-19-20-38.png differ diff --git a/Java基础教程/Java语言基础/image/2022-07-11-22-24-04.png b/Java基础教程/Java语言基础/image/2022-07-11-22-24-04.png new file mode 100644 index 00000000..4baab3bb Binary files /dev/null and b/Java基础教程/Java语言基础/image/2022-07-11-22-24-04.png differ diff --git a/Java工具教程/1 maven教程.md b/Java工具教程/1 maven教程.md deleted file mode 100644 index e69de29b..00000000 diff --git a/Java工具教程/maven教程/1 maven教程.md b/Java工具教程/maven教程/1 maven教程.md new file mode 100644 index 00000000..bef140ba --- /dev/null +++ b/Java工具教程/maven教程/1 maven教程.md @@ -0,0 +1,115 @@ +## 1 maven基本概念 + +### 概念 + +1. 项目对象模型(Project Object Management,POM)。Maven 是一个项目管理工具,可以对 Java 项目进行构建、依赖管理。Maven利用一个中央信息片断能管理一个项目的构建、报告和文档等步骤。 + +![](image/2022-07-11-10-36-37.png) + + +### 作用 + +1. 项目构建。提供标准的跨平台的项目构建方法。 +2. 依赖管理。方便快捷地管理项目依赖的资源,避免资源间的版本冲突。 +3. 统一开发结构。提供标准的、统一的项目结构。 + + +### 仓库 +* 本地仓库:在本地维护的maven的仓库。 +* 远程仓库:不在电脑上的。 + * 中央仓库:maven维护的服务器上的仓库。 + * 私服仓库:在局域网内维护的仓库。一方面是快,小范围内进行共享的资源。 + + + +### 坐标 +坐标的组成。坐标也是仓库中存放包的路径。 +* groupId:定义当前maven项目所属的组织名称,域名反写 +* artifactId:定义当前maven项目的名称。通常是模块名字 +* version:定义当前版本号。 + +> packaging 能够规定打包方式。例如可以打包成jar/war + +使用唯一标识。定位资源的位置。 + +### 镜像 + +* 在maven目录conf下的setting.xml中可以配置全局镜像mirrors +* 在.m2目录下的setting.xml中可以配置用户镜像mirrors + + + + +## 2 Maven项目构建 + + +### 工程目录结构 + +``` +工程-项目-src源代码+target编译结果-main+test-java+resource-groupId-fileID +``` + +1. 最顶层是工程,次顶层是模块或项目,可以自行编译执行的模块或项目。模块或项目下有src和target目录,即源代码和编译生成的代码。 +![](image/2022-07-11-11-56-50.png) + + +2. 在src同层目录下创建pom.xml。即模块或项目的顶层目录下使用pom.xml进行配置。 + +```xml + + + 4.0.0 + + com.ykl + project-maven + 1.0.2 + + jar + + + junit + junit + 4.12 + + + +``` + + +### maven命令 + +* mvn compile 下载插件、下载依赖、编译项目的源代码、将编译后的代码放到target目录下。 +* mvn clean 删除target目录,即本项目编译生成的文件。 +* mvn test 下载对应插件,编译后,运行Test目录下的测试脚本。 +* mvn package 首先进行compile,然后进行test,最后打包程序。 +* mvn install 把打包好的jar包放到仓库里。一次运行compile/test/package命令,最后将jar包安装到本地仓库中。 + + +### maven创建工程 +maven提供了工程创建的命令 +1. 创建一个java工程 +```shell +mvn archetype:generate -DgroupId=com.demo -DartifactId=javaproject -DarchetypeArtifactId=maven-archetype-quickstart -Dversion=0.0.1-snapshot -DinteractiveMode=false +``` +2. 创建一个web工程 + +``` +mvn archetype:generate -DgroupId=com.demo -DartifactId=webproject -DarchetypeArtifactId=maven-archetype-webapp -Dversion=0.0.1-snapshot -DinteractiveMode=false +``` + +![](image/2022-07-11-13-20-18.png) + + +### idea创建maven工程 + +1. 需要自己指定源代码、测试代码、源代码资源文件和测试资源文件。 +2. 可以在idea中自动创建启动参数。edit configuration +3. 使用原型创建Maven模块。选择不同的Maven原型文件。 + + +### idea创建web项目 + +1. 直接在web中添加tomcat插件,即可在本地展示网站。 + diff --git a/Java工具教程/maven教程/image/2022-07-11-10-36-37.png b/Java工具教程/maven教程/image/2022-07-11-10-36-37.png new file mode 100644 index 00000000..95b5c8c4 Binary files /dev/null and b/Java工具教程/maven教程/image/2022-07-11-10-36-37.png differ diff --git a/Java工具教程/maven教程/image/2022-07-11-11-40-25.png b/Java工具教程/maven教程/image/2022-07-11-11-40-25.png new file mode 100644 index 00000000..6f6f45df Binary files /dev/null and b/Java工具教程/maven教程/image/2022-07-11-11-40-25.png differ diff --git a/Java工具教程/maven教程/image/2022-07-11-11-56-50.png b/Java工具教程/maven教程/image/2022-07-11-11-56-50.png new file mode 100644 index 00000000..a2ccf2e3 Binary files /dev/null and b/Java工具教程/maven教程/image/2022-07-11-11-56-50.png differ diff --git a/Java工具教程/maven教程/image/2022-07-11-13-20-18.png b/Java工具教程/maven教程/image/2022-07-11-13-20-18.png new file mode 100644 index 00000000..152c2a9f Binary files /dev/null and b/Java工具教程/maven教程/image/2022-07-11-13-20-18.png differ diff --git a/Java工具教程/maven教程/project/project-maven/pom.xml b/Java工具教程/maven教程/project/project-maven/pom.xml new file mode 100644 index 00000000..4642045c --- /dev/null +++ b/Java工具教程/maven教程/project/project-maven/pom.xml @@ -0,0 +1,21 @@ + + + 4.0.0 + + com.ykl + project-maven + 1.0.2 + + jar + + + junit + junit + 4.12 + + + + + \ No newline at end of file diff --git a/Java工具教程/maven教程/project/project-maven/src/main/java/com/ykl/Demo.java b/Java工具教程/maven教程/project/project-maven/src/main/java/com/ykl/Demo.java new file mode 100644 index 00000000..37969211 --- /dev/null +++ b/Java工具教程/maven教程/project/project-maven/src/main/java/com/ykl/Demo.java @@ -0,0 +1,13 @@ +package com.ykl; + + +public class Demo{ + public static void main(String[] args) { + System.out.println("Hello World!"); + } + public String say(String name) { + System.out.println("hello"+name); + + return "hello "+name; + } +} \ No newline at end of file diff --git a/Java工具教程/maven教程/project/project-maven/src/test/java/com/ykl/TestDemo.java b/Java工具教程/maven教程/project/project-maven/src/test/java/com/ykl/TestDemo.java new file mode 100644 index 00000000..d5760179 --- /dev/null +++ b/Java工具教程/maven教程/project/project-maven/src/test/java/com/ykl/TestDemo.java @@ -0,0 +1,12 @@ +package com.ykl; + +import org.junit.Test; +import org.junit.Assert; +public class TestDemo { + @Test + public void testSay(){ + Demo d = new Demo(); + String ret = d.say("world"); + Assert.assertEquals("hello world", ret); + } +} diff --git a/Java源代码/.idea/.gitignore b/Java源代码/.idea/.gitignore new file mode 100644 index 00000000..0a8642fa --- /dev/null +++ b/Java源代码/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Zeppelin ignored files +/ZeppelinRemoteNotebooks/ diff --git a/Java源代码/.idea/ConfPoetryConfig.xml b/Java源代码/.idea/ConfPoetryConfig.xml new file mode 100644 index 00000000..a492c89d --- /dev/null +++ b/Java源代码/.idea/ConfPoetryConfig.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/Java源代码/.idea/Java源代码.iml b/Java源代码/.idea/Java源代码.iml new file mode 100644 index 00000000..d6ebd480 --- /dev/null +++ b/Java源代码/.idea/Java源代码.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Java源代码/.idea/inspectionProfiles/Project_Default.xml b/Java源代码/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 00000000..c6bd9f3d --- /dev/null +++ b/Java源代码/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,33 @@ + + + + \ No newline at end of file diff --git a/Java源代码/.idea/misc.xml b/Java源代码/.idea/misc.xml new file mode 100644 index 00000000..639900d1 --- /dev/null +++ b/Java源代码/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Java源代码/.idea/modules.xml b/Java源代码/.idea/modules.xml new file mode 100644 index 00000000..ced7346c --- /dev/null +++ b/Java源代码/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Java源代码/.idea/vcs.xml b/Java源代码/.idea/vcs.xml new file mode 100644 index 00000000..6c0b8635 --- /dev/null +++ b/Java源代码/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Java源代码/Lesson03/.idea/.gitignore b/Java源代码/Lesson03/.idea/.gitignore new file mode 100644 index 00000000..0a8642fa --- /dev/null +++ b/Java源代码/Lesson03/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Zeppelin ignored files +/ZeppelinRemoteNotebooks/ diff --git a/Java源代码/Lesson03/.idea/ConfPoetryConfig.xml b/Java源代码/Lesson03/.idea/ConfPoetryConfig.xml new file mode 100644 index 00000000..a492c89d --- /dev/null +++ b/Java源代码/Lesson03/.idea/ConfPoetryConfig.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/Java源代码/Lesson03/.idea/compiler.xml b/Java源代码/Lesson03/.idea/compiler.xml new file mode 100644 index 00000000..7f7e5348 --- /dev/null +++ b/Java源代码/Lesson03/.idea/compiler.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Java源代码/Lesson03/.idea/encodings.xml b/Java源代码/Lesson03/.idea/encodings.xml new file mode 100644 index 00000000..4bedd850 --- /dev/null +++ b/Java源代码/Lesson03/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Java源代码/Lesson03/.idea/inspectionProfiles/Project_Default.xml b/Java源代码/Lesson03/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 00000000..c6bd9f3d --- /dev/null +++ b/Java源代码/Lesson03/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,33 @@ + + + + \ No newline at end of file diff --git a/Java源代码/Lesson03/.idea/jarRepositories.xml b/Java源代码/Lesson03/.idea/jarRepositories.xml new file mode 100644 index 00000000..74cbb213 --- /dev/null +++ b/Java源代码/Lesson03/.idea/jarRepositories.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Java源代码/Lesson03/.idea/misc.xml b/Java源代码/Lesson03/.idea/misc.xml new file mode 100644 index 00000000..68e00fa8 --- /dev/null +++ b/Java源代码/Lesson03/.idea/misc.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/Java源代码/Lesson03/.idea/modules.xml b/Java源代码/Lesson03/.idea/modules.xml new file mode 100644 index 00000000..123d848f --- /dev/null +++ b/Java源代码/Lesson03/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Java源代码/Lesson03/.idea/vcs.xml b/Java源代码/Lesson03/.idea/vcs.xml new file mode 100644 index 00000000..b2bdec2d --- /dev/null +++ b/Java源代码/Lesson03/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Java源代码/Lesson02/Lesson02.iml b/Java源代码/Lesson03/Lesson03.iml similarity index 100% rename from Java源代码/Lesson02/Lesson02.iml rename to Java源代码/Lesson03/Lesson03.iml diff --git a/Java源代码/Lesson03/basicLesson/pom.xml b/Java源代码/Lesson03/basicLesson/pom.xml new file mode 100644 index 00000000..73e49423 --- /dev/null +++ b/Java源代码/Lesson03/basicLesson/pom.xml @@ -0,0 +1,12 @@ + + + 4.0.0 + + org.example + basicLesson + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git a/Java源代码/Lesson03/basicLesson/src/main/java/com/ykl/Application.java b/Java源代码/Lesson03/basicLesson/src/main/java/com/ykl/Application.java new file mode 100644 index 00000000..89974838 --- /dev/null +++ b/Java源代码/Lesson03/basicLesson/src/main/java/com/ykl/Application.java @@ -0,0 +1,17 @@ +/** + * Alipay.com Inc. + * Copyright (c) 2004-2022 All Rights Reserved. + */ +package com.ykl; + +/** + * @author yinkanglong + * @version : Application, v 0.1 2022-07-11 09:20 yinkanglong Exp $ + */ +public class Application { + public static void main(String[] args) { + System.out.println("hello world"); + + + } +} diff --git a/Java源代码/Lesson03/basicLesson/src/main/java/com/ykl/ExceptionTest.java b/Java源代码/Lesson03/basicLesson/src/main/java/com/ykl/ExceptionTest.java new file mode 100644 index 00000000..ee5b5126 --- /dev/null +++ b/Java源代码/Lesson03/basicLesson/src/main/java/com/ykl/ExceptionTest.java @@ -0,0 +1,27 @@ +/** + * Alipay.com Inc. + * Copyright (c) 2004-2022 All Rights Reserved. + */ +package com.ykl; + +/** + * @author yinkanglong + * @version : ExceptionTest, v 0.1 2022-07-11 19:45 yinkanglong Exp $ + */ +public class ExceptionTest { + + public static void main(String args[]) { + int a[] = new int[2]; + try { + System.out.println("Access element three :" + a[3]); + } catch (ArrayIndexOutOfBoundsException e) { + System.out.println("Exception thrown :" + e); + return ; + } finally { + a[0] = 6; + System.out.println("First element value: " + a[0]); + System.out.println("The finally statement is executed"); + } + } +} + diff --git a/Java源代码/Lesson03/untitled/pom.xml b/Java源代码/Lesson03/untitled/pom.xml new file mode 100644 index 00000000..980af153 --- /dev/null +++ b/Java源代码/Lesson03/untitled/pom.xml @@ -0,0 +1,12 @@ + + + 4.0.0 + + org.example + untitled + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git a/Java源代码/Lesson03/web-project/pom.xml b/Java源代码/Lesson03/web-project/pom.xml new file mode 100644 index 00000000..fa4921b7 --- /dev/null +++ b/Java源代码/Lesson03/web-project/pom.xml @@ -0,0 +1,67 @@ + + + + 4.0.0 + + org.example + web-project + 1.0-SNAPSHOT + war + + web-project Maven Webapp + + http://www.example.com + + + UTF-8 + 1.7 + 1.7 + + + + + junit + junit + 4.11 + test + + + + + web-project + + + + maven-clean-plugin + 3.1.0 + + + + maven-resources-plugin + 3.0.2 + + + maven-compiler-plugin + 3.8.0 + + + maven-surefire-plugin + 2.22.1 + + + maven-war-plugin + 3.2.2 + + + maven-install-plugin + 2.5.2 + + + maven-deploy-plugin + 2.8.2 + + + + + diff --git a/Java源代码/Lesson03/web-project/src/main/webapp/WEB-INF/web.xml b/Java源代码/Lesson03/web-project/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..9f88c1f9 --- /dev/null +++ b/Java源代码/Lesson03/web-project/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,7 @@ + + + + Archetype Created Web Application + diff --git a/Java源代码/Lesson03/web-project/src/main/webapp/index.jsp b/Java源代码/Lesson03/web-project/src/main/webapp/index.jsp new file mode 100644 index 00000000..c38169bb --- /dev/null +++ b/Java源代码/Lesson03/web-project/src/main/webapp/index.jsp @@ -0,0 +1,5 @@ + + +

Hello World!

+ + diff --git a/Java源代码/allclasses-frame.html b/Java源代码/allclasses-frame.html deleted file mode 100644 index ad2afba1..00000000 --- a/Java源代码/allclasses-frame.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - -所有类 - - - - - -

所有类

-
- -
- - diff --git a/Java源代码/allclasses-noframe.html b/Java源代码/allclasses-noframe.html deleted file mode 100644 index ebe02bea..00000000 --- a/Java源代码/allclasses-noframe.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - -所有类 - - - - - -

所有类

-
- -
- - diff --git a/Java源代码/constant-values.html b/Java源代码/constant-values.html deleted file mode 100644 index 6bc2cfd4..00000000 --- a/Java源代码/constant-values.html +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - -常量字段值 - - - - - - - - - - - -
-

常量字段值

-

目录

-
- - - - - - diff --git a/Java源代码/deprecated-list.html b/Java源代码/deprecated-list.html deleted file mode 100644 index 80d2074a..00000000 --- a/Java源代码/deprecated-list.html +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - -已过时的列表 - - - - - - - - -
- - - - - - - -
- - -
-

已过时的 API

-

目录

-
- -
- - - - - - - -
- - - - diff --git a/Java源代码/help-doc.html b/Java源代码/help-doc.html deleted file mode 100644 index d8f272e4..00000000 --- a/Java源代码/help-doc.html +++ /dev/null @@ -1,224 +0,0 @@ - - - - - - -API 帮助 - - - - - - - - -
- - - - - - - -
- - -
-

此 API 文档的组织方式

-
此 API (应用程序编程接口) 文档包含对应于导航栏中的项目的页面, 如下所述。
-
-
-
    -
  • -

    程序包

    -

    每个程序包都有一个页面, 其中包含它的类和接口的列表及其概要。此页面可以包含六个类别:

    -
      -
    • 接口 (斜体)
    • -
    • -
    • 枚举
    • -
    • 异常错误
    • -
    • 错误
    • -
    • 注释类型
    • -
    -
  • -
  • -

    类/接口

    -

    每个类, 接口, 嵌套类和嵌套接口都有各自的页面。其中每个页面都由三部分 (类/接口说明, 概要表, 以及详细的成员说明) 组成:

    -
      -
    • 类继承图
    • -
    • 直接子类
    • -
    • 所有已知子接口
    • -
    • 所有已知实现类
    • -
    • 类/接口声明
    • -
    • 类/接口说明
    • -
    -
      -
    • 嵌套类概要
    • -
    • 字段概要
    • -
    • 构造器概要
    • -
    • 方法概要
    • -
    -
      -
    • 字段详细资料
    • -
    • 构造器详细资料
    • -
    • 方法详细资料
    • -
    -

    每个概要条目都包含该项目的详细说明的第一句。概要条目按字母顺序排列, 而详细说明则按其在源代码中出现的顺序排列。这样保持了程序员所建立的逻辑分组。

    -
  • -
  • -

    注释类型

    -

    每个注释类型都有各自的页面, 其中包含以下部分:

    -
      -
    • 注释类型声明
    • -
    • 注释类型说明
    • -
    • 必需元素概要
    • -
    • 可选元素概要
    • -
    • 元素详细资料
    • -
    -
  • -
  • -

    枚举

    -

    每个枚举都有各自的页面, 其中包含以下部分:

    -
      -
    • 枚举声明
    • -
    • 枚举说明
    • -
    • 枚举常量概要
    • -
    • 枚举常量详细资料
    • -
    -
  • -
  • -

    使用

    -

    每个已文档化的程序包, 类和接口都有各自的“使用”页面。此页面介绍了使用给定类或程序包的任何部分的程序包, 类, 方法, 构造器和字段。对于给定的类或接口 A, 其“使用”页面包含 A 的子类, 声明为 A 的字段, 返回 A 的方法, 以及带有类型为 A 的参数的方法和构造器。访问此页面的方法是: 首先转至程序包, 类或接口, 然后单击导航栏中的 "使用" 链接。

    -
  • -
  • -

    树 (类分层结构)

    -

    对于所有程序包, 有一个类分层结构页面, 以及每个程序包的分层结构。每个分层结构页面都包含类的列表和接口的列表。从java.lang.Object开始, 按继承结构对类进行排列。接口不从java.lang.Object继承。

    -
      -
    • 查看“概览”页面时, 单击 "树" 将显示所有程序包的分层结构。
    • -
    • 查看特定程序包, 类或接口页面时, 单击 "树" 将仅显示该程序包的分层结构。
    • -
    -
  • -
  • -

    已过时的 API

    -

    已过时的 API 页面列出了所有已过时的 API。一般由于进行了改进并且通常提供了替代的 API, 所以建议不要使用已过时的 API。在将来的实现过程中, 可能会删除已过时的 API。

    -
  • -
  • -

    索引

    -

    索引 包含按字母顺序排列的所有类, 接口, 构造器, 方法和字段的列表。

    -
  • -
  • -

    上一个/下一个

    -

    这些链接使您可以转至下一个或上一个类, 接口, 程序包或相关页面。

    -
  • -
  • -

    框架/无框架

    -

    这些链接用于显示和隐藏 HTML 框架。所有页面均具有有框架和无框架两种显示方式。

    -
  • -
  • -

    所有类

    -

    所有类链接显示所有类和接口 (除了非静态嵌套类型)。

    -
  • -
  • -

    序列化表格

    -

    每个可序列化或可外部化的类都有其序列化字段和方法的说明。此信息对重新实现者有用, 而对使用 API 的开发者则没有什么用处。尽管导航栏中没有链接, 但您可以通过下列方式获取此信息: 转至任何序列化类, 然后单击类说明的 "另请参阅" 部分中的 "序列化表格"。

    -
  • -
  • -

    常量字段值

    -

    常量字段值页面列出了静态最终字段及其值。

    -
  • -
-此帮助文件适用于使用标准 doclet 生成的 API 文档。
- -
- - - - - - - -
- - - - diff --git a/Java源代码/index.html b/Java源代码/index.html deleted file mode 100644 index b555fbf2..00000000 --- a/Java源代码/index.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - -生成的文档 (无标题) - - - - - - -<noscript> -<div>您的浏览器已禁用 JavaScript。</div> -</noscript> -<h2>框架预警</h2> -<p>请使用框架功能查看此文档。如果看到此消息, 则表明您使用的是不支持框架的 Web 客户机。链接到<a href="com/ykl/package-summary.html">非框架版本</a>。</p> - - - diff --git a/Java源代码/overview-tree.html b/Java源代码/overview-tree.html deleted file mode 100644 index c4e20a02..00000000 --- a/Java源代码/overview-tree.html +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - -类分层结构 - - - - - - - - - - - -
-

所有程序包的分层结构

-程序包分层结构: - -
-
-

类分层结构

- -
- - - - - - diff --git a/Java源代码/package-list b/Java源代码/package-list deleted file mode 100644 index 46b04614..00000000 --- a/Java源代码/package-list +++ /dev/null @@ -1 +0,0 @@ -com.ykl diff --git a/Java源代码/script.js b/Java源代码/script.js deleted file mode 100644 index b3463569..00000000 --- a/Java源代码/script.js +++ /dev/null @@ -1,30 +0,0 @@ -function show(type) -{ - count = 0; - for (var key in methods) { - var row = document.getElementById(key); - if ((methods[key] & type) != 0) { - row.style.display = ''; - row.className = (count++ % 2) ? rowColor : altColor; - } - else - row.style.display = 'none'; - } - updateTabs(type); -} - -function updateTabs(type) -{ - for (var value in tabs) { - var sNode = document.getElementById(tabs[value][0]); - var spanNode = sNode.firstChild; - if (value == type) { - sNode.className = activeTableTab; - spanNode.innerHTML = tabs[value][1]; - } - else { - sNode.className = tableTab; - spanNode.innerHTML = "" + tabs[value][1] + ""; - } - } -} diff --git a/Java源代码/stylesheet.css b/Java源代码/stylesheet.css deleted file mode 100644 index 98055b22..00000000 --- a/Java源代码/stylesheet.css +++ /dev/null @@ -1,574 +0,0 @@ -/* Javadoc style sheet */ -/* -Overall document style -*/ - -@import url('resources/fonts/dejavu.css'); - -body { - background-color:#ffffff; - color:#353833; - font-family:'DejaVu Sans', Arial, Helvetica, sans-serif; - font-size:14px; - margin:0; -} -a:link, a:visited { - text-decoration:none; - color:#4A6782; -} -a:hover, a:focus { - text-decoration:none; - color:#bb7a2a; -} -a:active { - text-decoration:none; - color:#4A6782; -} -a[name] { - color:#353833; -} -a[name]:hover { - text-decoration:none; - color:#353833; -} -pre { - font-family:'DejaVu Sans Mono', monospace; - font-size:14px; -} -h1 { - font-size:20px; -} -h2 { - font-size:18px; -} -h3 { - font-size:16px; - font-style:italic; -} -h4 { - font-size:13px; -} -h5 { - font-size:12px; -} -h6 { - font-size:11px; -} -ul { - list-style-type:disc; -} -code, tt { - font-family:'DejaVu Sans Mono', monospace; - font-size:14px; - padding-top:4px; - margin-top:8px; - line-height:1.4em; -} -dt code { - font-family:'DejaVu Sans Mono', monospace; - font-size:14px; - padding-top:4px; -} -table tr td dt code { - font-family:'DejaVu Sans Mono', monospace; - font-size:14px; - vertical-align:top; - padding-top:4px; -} -sup { - font-size:8px; -} -/* -Document title and Copyright styles -*/ -.clear { - clear:both; - height:0px; - overflow:hidden; -} -.aboutLanguage { - float:right; - padding:0px 21px; - font-size:11px; - z-index:200; - margin-top:-9px; -} -.legalCopy { - margin-left:.5em; -} -.bar a, .bar a:link, .bar a:visited, .bar a:active { - color:#FFFFFF; - text-decoration:none; -} -.bar a:hover, .bar a:focus { - color:#bb7a2a; -} -.tab { - background-color:#0066FF; - color:#ffffff; - padding:8px; - width:5em; - font-weight:bold; -} -/* -Navigation bar styles -*/ -.bar { - background-color:#4D7A97; - color:#FFFFFF; - padding:.8em .5em .4em .8em; - height:auto;/*height:1.8em;*/ - font-size:11px; - margin:0; -} -.topNav { - background-color:#4D7A97; - color:#FFFFFF; - float:left; - padding:0; - width:100%; - clear:right; - height:2.8em; - padding-top:10px; - overflow:hidden; - font-size:12px; -} -.bottomNav { - margin-top:10px; - background-color:#4D7A97; - color:#FFFFFF; - float:left; - padding:0; - width:100%; - clear:right; - height:2.8em; - padding-top:10px; - overflow:hidden; - font-size:12px; -} -.subNav { - background-color:#dee3e9; - float:left; - width:100%; - overflow:hidden; - font-size:12px; -} -.subNav div { - clear:left; - float:left; - padding:0 0 5px 6px; - text-transform:uppercase; -} -ul.navList, ul.subNavList { - float:left; - margin:0 25px 0 0; - padding:0; -} -ul.navList li{ - list-style:none; - float:left; - padding: 5px 6px; - text-transform:uppercase; -} -ul.subNavList li{ - list-style:none; - float:left; -} -.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited { - color:#FFFFFF; - text-decoration:none; - text-transform:uppercase; -} -.topNav a:hover, .bottomNav a:hover { - text-decoration:none; - color:#bb7a2a; - text-transform:uppercase; -} -.navBarCell1Rev { - background-color:#F8981D; - color:#253441; - margin: auto 5px; -} -.skipNav { - position:absolute; - top:auto; - left:-9999px; - overflow:hidden; -} -/* -Page header and footer styles -*/ -.header, .footer { - clear:both; - margin:0 20px; - padding:5px 0 0 0; -} -.indexHeader { - margin:10px; - position:relative; -} -.indexHeader span{ - margin-right:15px; -} -.indexHeader h1 { - font-size:13px; -} -.title { - color:#2c4557; - margin:10px 0; -} -.subTitle { - margin:5px 0 0 0; -} -.header ul { - margin:0 0 15px 0; - padding:0; -} -.footer ul { - margin:20px 0 5px 0; -} -.header ul li, .footer ul li { - list-style:none; - font-size:13px; -} -/* -Heading styles -*/ -div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { - background-color:#dee3e9; - border:1px solid #d0d9e0; - margin:0 0 6px -8px; - padding:7px 5px; -} -ul.blockList ul.blockList ul.blockList li.blockList h3 { - background-color:#dee3e9; - border:1px solid #d0d9e0; - margin:0 0 6px -8px; - padding:7px 5px; -} -ul.blockList ul.blockList li.blockList h3 { - padding:0; - margin:15px 0; -} -ul.blockList li.blockList h2 { - padding:0px 0 20px 0; -} -/* -Page layout container styles -*/ -.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer { - clear:both; - padding:10px 20px; - position:relative; -} -.indexContainer { - margin:10px; - position:relative; - font-size:12px; -} -.indexContainer h2 { - font-size:13px; - padding:0 0 3px 0; -} -.indexContainer ul { - margin:0; - padding:0; -} -.indexContainer ul li { - list-style:none; - padding-top:2px; -} -.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt { - font-size:12px; - font-weight:bold; - margin:10px 0 0 0; - color:#4E4E4E; -} -.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { - margin:5px 0 10px 0px; - font-size:14px; - font-family:'DejaVu Sans Mono',monospace; -} -.serializedFormContainer dl.nameValue dt { - margin-left:1px; - font-size:1.1em; - display:inline; - font-weight:bold; -} -.serializedFormContainer dl.nameValue dd { - margin:0 0 0 1px; - font-size:1.1em; - display:inline; -} -/* -List styles -*/ -ul.horizontal li { - display:inline; - font-size:0.9em; -} -ul.inheritance { - margin:0; - padding:0; -} -ul.inheritance li { - display:inline; - list-style:none; -} -ul.inheritance li ul.inheritance { - margin-left:15px; - padding-left:15px; - padding-top:1px; -} -ul.blockList, ul.blockListLast { - margin:10px 0 10px 0; - padding:0; -} -ul.blockList li.blockList, ul.blockListLast li.blockList { - list-style:none; - margin-bottom:15px; - line-height:1.4; -} -ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList { - padding:0px 20px 5px 10px; - border:1px solid #ededed; - background-color:#f8f8f8; -} -ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList { - padding:0 0 5px 8px; - background-color:#ffffff; - border:none; -} -ul.blockList ul.blockList ul.blockList ul.blockList li.blockList { - margin-left:0; - padding-left:0; - padding-bottom:15px; - border:none; -} -ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast { - list-style:none; - border-bottom:none; - padding-bottom:0; -} -table tr td dl, table tr td dl dt, table tr td dl dd { - margin-top:0; - margin-bottom:1px; -} -/* -Table styles -*/ -.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary { - width:100%; - border-left:1px solid #EEE; - border-right:1px solid #EEE; - border-bottom:1px solid #EEE; -} -.overviewSummary, .memberSummary { - padding:0px; -} -.overviewSummary caption, .memberSummary caption, .typeSummary caption, -.useSummary caption, .constantsSummary caption, .deprecatedSummary caption { - position:relative; - text-align:left; - background-repeat:no-repeat; - color:#253441; - font-weight:bold; - clear:none; - overflow:hidden; - padding:0px; - padding-top:10px; - padding-left:1px; - margin:0px; - white-space:pre; -} -.overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link, -.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link, -.overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover, -.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover, -.overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active, -.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active, -.overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited, -.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited { - color:#FFFFFF; -} -.overviewSummary caption span, .memberSummary caption span, .typeSummary caption span, -.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span { - white-space:nowrap; - padding-top:5px; - padding-left:12px; - padding-right:12px; - padding-bottom:7px; - display:inline-block; - float:left; - background-color:#F8981D; - border: none; - height:16px; -} -.memberSummary caption span.activeTableTab span { - white-space:nowrap; - padding-top:5px; - padding-left:12px; - padding-right:12px; - margin-right:3px; - display:inline-block; - float:left; - background-color:#F8981D; - height:16px; -} -.memberSummary caption span.tableTab span { - white-space:nowrap; - padding-top:5px; - padding-left:12px; - padding-right:12px; - margin-right:3px; - display:inline-block; - float:left; - background-color:#4D7A97; - height:16px; -} -.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab { - padding-top:0px; - padding-left:0px; - padding-right:0px; - background-image:none; - float:none; - display:inline; -} -.overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd, -.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd { - display:none; - width:5px; - position:relative; - float:left; - background-color:#F8981D; -} -.memberSummary .activeTableTab .tabEnd { - display:none; - width:5px; - margin-right:3px; - position:relative; - float:left; - background-color:#F8981D; -} -.memberSummary .tableTab .tabEnd { - display:none; - width:5px; - margin-right:3px; - position:relative; - background-color:#4D7A97; - float:left; - -} -.overviewSummary td, .memberSummary td, .typeSummary td, -.useSummary td, .constantsSummary td, .deprecatedSummary td { - text-align:left; - padding:0px 0px 12px 10px; -} -th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th, -td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{ - vertical-align:top; - padding-right:0px; - padding-top:8px; - padding-bottom:3px; -} -th.colFirst, th.colLast, th.colOne, .constantsSummary th { - background:#dee3e9; - text-align:left; - padding:8px 3px 3px 7px; -} -td.colFirst, th.colFirst { - white-space:nowrap; - font-size:13px; -} -td.colLast, th.colLast { - font-size:13px; -} -td.colOne, th.colOne { - font-size:13px; -} -.overviewSummary td.colFirst, .overviewSummary th.colFirst, -.useSummary td.colFirst, .useSummary th.colFirst, -.overviewSummary td.colOne, .overviewSummary th.colOne, -.memberSummary td.colFirst, .memberSummary th.colFirst, -.memberSummary td.colOne, .memberSummary th.colOne, -.typeSummary td.colFirst{ - width:25%; - vertical-align:top; -} -td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover { - font-weight:bold; -} -.tableSubHeadingColor { - background-color:#EEEEFF; -} -.altColor { - background-color:#FFFFFF; -} -.rowColor { - background-color:#EEEEEF; -} -/* -Content styles -*/ -.description pre { - margin-top:0; -} -.deprecatedContent { - margin:0; - padding:10px 0; -} -.docSummary { - padding:0; -} - -ul.blockList ul.blockList ul.blockList li.blockList h3 { - font-style:normal; -} - -div.block { - font-size:14px; - font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif; -} - -td.colLast div { - padding-top:0px; -} - - -td.colLast a { - padding-bottom:3px; -} -/* -Formatting effect styles -*/ -.sourceLineNo { - color:green; - padding:0 30px 0 0; -} -h1.hidden { - visibility:hidden; - overflow:hidden; - font-size:10px; -} -.block { - display:block; - margin:3px 10px 2px 0px; - color:#474747; -} -.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink, -.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel, -.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink { - font-weight:bold; -} -.deprecationComment, .emphasizedPhrase, .interfaceName { - font-style:italic; -} - -div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase, -div.block div.block span.interfaceName { - font-style:normal; -} - -div.contentContainer ul.blockList li.blockList h2{ - padding-bottom:0px; -}