├── .gitignore ├── .gitattributes ├── src ├── 第3章Java的基本程序设计结构 │ ├── 3.7输入输出 │ │ ├── inFile.txt │ │ ├── outFile.txt │ │ ├── ConsoleTest.java │ │ ├── ScannerAPI.java │ │ ├── InputTest.java │ │ └── IOTest.java │ ├── 3.1一个简单的Java应用程序 │ │ └── FirstSample.java │ ├── 3.4变量 │ │ ├── Constants.java │ │ └── Constants2.java │ ├── 3.6字符串 │ │ ├── TestStringBuilder.java │ │ ├── StringJoin.java │ │ ├── StringBuilderAPI.java │ │ ├── StringEqual.java │ │ ├── CodePoint.java │ │ └── StringAPI.java │ ├── 3.10数组 │ │ ├── Message.java │ │ ├── IrragularArray.java │ │ ├── LotteryDrawing.java │ │ ├── ArrayCopyTest.java │ │ └── ArraysAPI.java │ ├── 3.9大数值 │ │ ├── BigIntegerAPI.java │ │ └── BigDecimalAPI.java │ ├── 3.8控制流程 │ │ ├── ContinueTest.java │ │ └── FallThroughTest.java │ └── 3.5运算符 │ │ └── ModAndFloorMod.java ├── 第9章集合 │ ├── 9.6遗留的集合 │ │ ├── StackAPI.java │ │ ├── EnumerationAPI.java │ │ ├── BitSetAPI.java │ │ ├── PropertiesAPI.java │ │ └── Sieve.java │ ├── 9.2具体的集合 │ │ ├── PriorityQueueAPI.java │ │ ├── SetAPI.java │ │ ├── LinkedListAPI.java │ │ ├── PriorityQueueTest.java │ │ ├── SetTest.java │ │ ├── TreeSetAPI.java │ │ ├── ListAPI.java │ │ ├── QueueAPI.java │ │ ├── LinkedListTest.java │ │ └── TreeSetTest.java │ ├── 9.5算法 │ │ ├── BinarySearchAPI.java │ │ ├── ShuffleTest.java │ │ ├── SortShuffleAPI.java │ │ └── SimpleAlgorithmAPI.java │ ├── 9.3映射 │ │ ├── MapViewAPI.java │ │ ├── MapAPI.java │ │ ├── MapUpdateAPI.java │ │ ├── MapTest.java │ │ └── SpecialSetMapAPI.java │ └── 9.4视图与包装器 │ │ └── CollectionsAPI.java ├── 第5章继承 │ ├── 5.1类超类和子类 │ │ ├── abstractClasses │ │ │ ├── Person.java │ │ │ ├── Student.java │ │ │ ├── PersonTest.java │ │ │ └── Employee.java │ │ └── inharitance │ │ │ ├── Manager.java │ │ │ ├── ManagerTest.java │ │ │ └── Employee.java │ ├── 5.7反射 │ │ ├── objectAnalyzer │ │ │ ├── ObjectAnalyzerTest.java │ │ │ └── ObjectAnalyzer.java │ │ ├── MethodTableTest.java │ │ ├── CopyOfTest.java │ │ ├── ClassReflectAPI.java │ │ ├── ReflectionTest.java │ │ └── ClassNameTest.java │ ├── 5.2Object所有类的超类 │ │ ├── ClassAPI.java │ │ ├── HashCodeAPI.java │ │ ├── EqualsTest │ │ │ ├── Manager.java │ │ │ ├── Employee.java │ │ │ └── EqualsTest.java │ │ ├── EqualsTest.java │ │ ├── EqualsTest3.java │ │ └── EqualsTest2.java │ ├── 5.6枚举类 │ │ ├── EnumAPI.java │ │ └── EnumTest.java │ ├── 5.4对象包装器与自动装箱 │ │ └── IntegerAPI.java │ └── 5.3泛型数组列表 │ │ ├── ArrayListAPI.java │ │ └── arrayList │ │ └── ArrayListTest.java ├── 第2章Java程序设计环境 │ ├── 2.2使用命令行工具 │ │ └── Welcome.java │ ├── 2.5 构建并运行applet │ │ └── RoadApplet.java │ └── 2.4运用图形化应用程序 │ │ └── ImageViewer.java ├── 第7章异常断言和日志 │ ├── 7.1处理错误 │ │ └── ThrowableAPI.java │ ├── 7.4使用断言 │ │ └── ClassLoaderAPI.java │ └── 7.2捕获异常 │ │ ├── StackTraceTest.java │ │ └── ExceptionAPI.java ├── 第4章对象与类 │ ├── 4.7包 │ │ ├── PackageTest.java │ │ └── com │ │ │ └── mypackage │ │ │ └── Employee.java │ ├── 4.6对象构造 │ │ ├── ExplicitInit.java │ │ ├── CallAnotherConstructor.java │ │ ├── ConstructorTest.java │ │ └── ConstructOrderTest.java │ ├── 4.2使用预定义类 │ │ ├── DateAndLocalDate.java │ │ └── CalendarTest.java │ ├── 4.3用户自定义类 │ │ └── EmployeeTest.java │ ├── 4.4静态域域静态方法 │ │ └── StaticTest.java │ └── 4.5方法参数 │ │ └── ParamTest.java ├── 第6章接口lambda表达式与内部类 │ ├── 6.3lambda表达式 │ │ ├── ProcessLambda.java │ │ ├── MethodReferenceTest.java │ │ ├── LambdaTest.java │ │ └── ComparatorTest.java │ ├── 6.4内部类 │ │ ├── InnerClassStaticAndFinal.java │ │ ├── AnonymousInnerClassTest.java │ │ ├── InnerClassLocalParam.java │ │ ├── InnerClassTest.java │ │ └── StaticInnerClassTest.java │ ├── 6.2接口示例 │ │ ├── cloneTest │ │ │ ├── Manager.java │ │ │ ├── Employee.java │ │ │ └── CloneTest.java │ │ └── TimerTest.java │ ├── 6.5代理 │ │ ├── ProxyAPI.java │ │ └── ProxyTest.java │ └── 6.1接口 │ │ └── EmployeeSortTest.java └── 第8章泛型程序设计 │ ├── 8.9反射和泛型 │ ├── ClassAPI.java │ ├── GenericReflectionAPI.java │ └── GenericReflectionTest.java │ ├── 8.5泛型代码和虚拟机 │ ├── BridgeMethodTest2.java │ └── BridgeMethodTest.java │ ├── 8.6约束与局限性 │ └── ErasedCheckedTest.java │ ├── 8.2定义简单的泛型类 │ └── PairTest.java │ ├── 8.4类型变量的限定 │ └── PairTest2.java │ └── 8.8通配符类型 │ └── PairTest3.java ├── notes ├── Java核心技术卷一0.md ├── Java核心技术卷一1.md ├── Java核心技术卷一2.md ├── Java核心技术卷一6_3.md ├── Java核心技术卷一7_0.md ├── Java核心技术卷一7_2.md ├── Java核心技术卷一9_0.md ├── Java核心技术卷一4_0.md ├── Java核心技术卷一4_2.md ├── Java核心技术卷一8_1.md ├── Java核心技术卷一8_2.md ├── Java核心技术卷一8_3.md └── Java核心技术卷一5_0.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.class -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.7输入输出/inFile.txt: -------------------------------------------------------------------------------- 1 | Hello, world! 2 | hello hello 3 | 4 | 5 | 2333333333 -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.7输入输出/outFile.txt: -------------------------------------------------------------------------------- 1 | Hello, world! 2 | hello hello 3 | 4 | 5 | 2333333333 6 | -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.1一个简单的Java应用程序/FirstSample.java: -------------------------------------------------------------------------------- 1 | public class FirstSample { 2 | public static void main(String[] args) { 3 | System.out.println("We will not use 'Hello, World!'"); 4 | } 5 | } -------------------------------------------------------------------------------- /src/第9章集合/9.6遗留的集合/StackAPI.java: -------------------------------------------------------------------------------- 1 | public class StackAPI { 2 | public static void main(String[] args) { 3 | // java.util.Stack 4 | // E push(E item) 5 | 6 | // E pop() 7 | // 返回栈顶元素,并弹出 8 | 9 | // E peak() 10 | // 返回栈顶元素,不弹出 11 | } 12 | } -------------------------------------------------------------------------------- /src/第5章继承/5.1类超类和子类/abstractClasses/Person.java: -------------------------------------------------------------------------------- 1 | public abstract class Person { 2 | public abstract String getDescription(); 3 | 4 | private String name; 5 | 6 | public Person(String name) { 7 | this.name = name; 8 | } 9 | public String getName() { 10 | return name; 11 | } 12 | } -------------------------------------------------------------------------------- /src/第9章集合/9.2具体的集合/PriorityQueueAPI.java: -------------------------------------------------------------------------------- 1 | public class PriorityQueueAPI { 2 | public static void main(String[] args) { 3 | // java.util.PriorityQueue 4 | // PriorityQueue() 5 | // PriorityQueue(int initialCapacity) 6 | // PriorityQueue(itn initialCapacity, Comparator c) 7 | } 8 | } -------------------------------------------------------------------------------- /src/第2章Java程序设计环境/2.2使用命令行工具/Welcome.java: -------------------------------------------------------------------------------- 1 | public class Welcome { 2 | public static void main(String[] args) { 3 | String greeting = "Welcome to Core Java!"; 4 | System.out.println(greeting); 5 | for(int i = 0; i < greeting.length(); i++) 6 | System.out.print("="); 7 | System.out.println(); 8 | } 9 | } -------------------------------------------------------------------------------- /src/第9章集合/9.5算法/BinarySearchAPI.java: -------------------------------------------------------------------------------- 1 | public class BinarySearchAPI { 2 | public static void main(String[] args) { 3 | // java.util.Collections 4 | // static > int binarySearch(List elements, T key) 5 | // static int binarySearch(List elements, T key, Comparator c) 6 | } 7 | } -------------------------------------------------------------------------------- /src/第7章异常断言和日志/7.1处理错误/ThrowableAPI.java: -------------------------------------------------------------------------------- 1 | public class ThrowableAPI { 2 | public static void main(String[] args) { 3 | // java.lang.Throwable 4 | // Throwable() 5 | 6 | // Throwable(String message) 7 | // 附带详细信息 8 | 9 | // String getMessage() 10 | // 获得 Throwable 对象的详细信息 11 | } 12 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.4变量/Constants.java: -------------------------------------------------------------------------------- 1 | public class Constants { 2 | public static void main(String[] args) { 3 | final double CM_PER_INCH = 2.54; 4 | double paperWidth = 8.5; 5 | double paperHeight = 11; 6 | System.out.println("Paper size in centimeters: " 7 | + paperWidth * CM_PER_INCH + " by " 8 | + paperHeight * CM_PER_INCH); 9 | } 10 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.4变量/Constants2.java: -------------------------------------------------------------------------------- 1 | public class Constants2 { 2 | public static final double CM_PER_INCH = 2.54; 3 | public static void main(String[] args) { 4 | double paperWidth = 8.5; 5 | double paperHeight = 11; 6 | System.out.println("Paper size in centimeters: " 7 | + paperWidth * CM_PER_INCH + " by " 8 | + paperHeight * CM_PER_INCH); 9 | } 10 | } -------------------------------------------------------------------------------- /src/第5章继承/5.1类超类和子类/abstractClasses/Student.java: -------------------------------------------------------------------------------- 1 | public class Student extends Person { 2 | // private String name; 3 | private String major; 4 | public Student(String name, String major) { 5 | super(name); 6 | this.major = major; 7 | } 8 | public String getDescription() { 9 | return "A student majoring in " + major; 10 | } 11 | } -------------------------------------------------------------------------------- /src/第5章继承/5.7反射/objectAnalyzer/ObjectAnalyzerTest.java: -------------------------------------------------------------------------------- 1 | import java.util.ArrayList; 2 | 3 | public class ObjectAnalyzerTest { 4 | public static void main(String[] args) { 5 | ArrayList squares = new ArrayList<>(); 6 | for(int i = 1; i <= 5; i++) 7 | squares.add(i * i); 8 | System.out.println(new ObjectAnalyzer().toString(squares)); 9 | } 10 | } -------------------------------------------------------------------------------- /src/第4章对象与类/4.7包/PackageTest.java: -------------------------------------------------------------------------------- 1 | import com.mypackage.*; 2 | import static java.lang.System.*; 3 | 4 | public class PackageTest { 5 | public static void main(String[] args) { 6 | Employee harry = new Employee("Harry Hacker", 50000, 1989, 10, 1); 7 | 8 | harry.raiseSalary(5); 9 | 10 | out.println("name = " + harry.getName() + ", salary = " + harry.getSalary()); 11 | } 12 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.7输入输出/ConsoleTest.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | public class ConsoleTest { 3 | public static void main(String[] args) { 4 | Console cons = System.console(); 5 | String username = cons.readLine("User name: "); 6 | char[] passwd = cons.readPassword("Password: "); 7 | 8 | System.out.println("=========="); 9 | System.out.println(username); 10 | System.out.println(passwd); 11 | } 12 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.6字符串/TestStringBuilder.java: -------------------------------------------------------------------------------- 1 | public class TestStringBuilder { 2 | public static void main(String[] args) { 3 | StringBuilder builder = new StringBuilder(); 4 | char ch = 'a'; 5 | String str = "bcd"; 6 | builder.append(ch); 7 | builder.append(str); 8 | String completedString = builder.toString(); 9 | System.out.println(builder); 10 | System.out.println(completedString); 11 | } 12 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.7输入输出/ScannerAPI.java: -------------------------------------------------------------------------------- 1 | public class ScannerAPI { 2 | public static void main(String[] args) { 3 | // Scanner(InputStream in) 输入流创建对象 4 | 5 | // String nextLine() 读下一行内容 6 | 7 | // String next() 读下一个单词,空格间隔 8 | // int nextInt() 9 | // double nextDouble() 10 | 11 | // boolean hasNext() 是否还有下一个单词 12 | // boolean hasNextInt() 是否还有下一个整数 13 | // boolean hasNextDouble() 14 | } 15 | } -------------------------------------------------------------------------------- /src/第9章集合/9.3映射/MapViewAPI.java: -------------------------------------------------------------------------------- 1 | public class MapViewAPI { 2 | public static void main(String[] args) { 3 | // java.util.Map 4 | // Set> entrySet() 5 | // Set keySet() 6 | // Collection values() 7 | 8 | 9 | // java.util.Map.Entry 10 | // K getKey() 11 | // V getValue() 12 | // V setValue(V newValue) 13 | } 14 | } -------------------------------------------------------------------------------- /src/第9章集合/9.2具体的集合/SetAPI.java: -------------------------------------------------------------------------------- 1 | public class SetAPI { 2 | public static void main(String[] args) { 3 | // java.util.HashSet 4 | // HashSet() 5 | 6 | // HashSet(Collection elements) 7 | 8 | // HashSet(int initialCapacity) 9 | 10 | // HashSet(int initialCapacity, float loadFactor) 11 | 12 | 13 | // java.lang.Object 14 | // int hashCode() 15 | } 16 | } -------------------------------------------------------------------------------- /src/第6章接口lambda表达式与内部类/6.3lambda表达式/ProcessLambda.java: -------------------------------------------------------------------------------- 1 | public class ProcessLambda { 2 | public static void main(String[] args) { 3 | repeat(10, i -> System.out.println("Countdown : " + (9 - i))); 4 | } 5 | public static void repeat(int n, IntConsumer action) { 6 | for(int i = 0; i < n; i++) 7 | action.accept(i); 8 | } 9 | } 10 | interface IntConsumer { 11 | void accept(int value); 12 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.10数组/Message.java: -------------------------------------------------------------------------------- 1 | public class Message { 2 | public static void main(String[] args) { 3 | if(args.length == 0 || args[0].equals("-h")) 4 | System.out.print("Hello,"); 5 | else if(args[0].equals("-g")) 6 | System.out.print("Goodbye,"); 7 | else 8 | System.out.print(args[0] + ","); 9 | for(int i = 1; i < args.length; i++) 10 | System.out.print(" "+args[i]); 11 | System.out.println("!"); 12 | } 13 | } -------------------------------------------------------------------------------- /src/第6章接口lambda表达式与内部类/6.4内部类/InnerClassStaticAndFinal.java: -------------------------------------------------------------------------------- 1 | public class InnerClassStaticAndFinal { 2 | public static void main(String[] args) { 3 | //Outer.Inner.f(); 4 | } 5 | } 6 | 7 | class Outer { 8 | public static int v=5; 9 | class Inner { 10 | //static int vv=5; 11 | final static int vv=5; 12 | /*static void f() { 13 | System.out.println(v); 14 | }*/ 15 | } 16 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.7输入输出/InputTest.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class InputTest { 3 | public static void main(String[] args) { 4 | Scanner in = new Scanner(System.in); 5 | 6 | System.out.print("What is your name? "); 7 | String name = in.nextLine(); 8 | 9 | System.out.print("How old are you? "); 10 | int age = in.nextInt(); 11 | 12 | System.out.println("Hello, " + name + ". Next year, you'll be " + (age + 1)); 13 | } 14 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.9大数值/BigIntegerAPI.java: -------------------------------------------------------------------------------- 1 | public class BigIntegerAPI { 2 | public static void main(String[] args) { 3 | // BigInteger add(BigInteger other) 4 | // BigInteger subtract(BigInteger other) 5 | // BigInteger multiply(BigInteger other) 6 | // BigInteger divide(BigInteger other) 7 | // BigInteger mod(BigInteger other) 8 | 9 | // int compareTo(BigInteger other) 10 | 11 | // static BigInteger valueOf(long x) 12 | } 13 | } -------------------------------------------------------------------------------- /src/第5章继承/5.1类超类和子类/abstractClasses/PersonTest.java: -------------------------------------------------------------------------------- 1 | public class PersonTest { 2 | public static void main(String[] args) { 3 | Person[] people = new Person[2]; 4 | 5 | people[0] = new Employee("Harry Hacker", 50000, 1989, 10, 1); 6 | people[1] = new Student("Maria Morris", "computer science"); 7 | 8 | for(Person p : people) 9 | System.out.println(p.getName() + " : " + p.getDescription()); 10 | } 11 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.8控制流程/ContinueTest.java: -------------------------------------------------------------------------------- 1 | public class ContinueTest { 2 | public static void main(String[] args) { 3 | label1: 4 | for(int i=0;i<10;i++) { 5 | System.out.println("out i = " + i); 6 | for(int j=0;j<5;j++) { 7 | System.out.print("in loop j = " + j + " "); 8 | if(i == 1 && j == 2) 9 | { 10 | System.out.println("\n!!!"); 11 | continue label1; 12 | } 13 | } 14 | System.out.println(); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/第9章集合/9.2具体的集合/LinkedListAPI.java: -------------------------------------------------------------------------------- 1 | public class LinkedListAPI { 2 | public static void main(String[] args) { 3 | // java.util.LinkedList 4 | // LinkedList() 5 | 6 | // LinkedList(Collection elements) 7 | 8 | // void addFirst(E element) 9 | // void addLast(E element) 10 | // E getFirst() 11 | // E getLast() 12 | // E removeFirst() 13 | // E removeLast() 14 | } 15 | } -------------------------------------------------------------------------------- /src/第9章集合/9.6遗留的集合/EnumerationAPI.java: -------------------------------------------------------------------------------- 1 | public class EnumerationAPI { 2 | public static void main(String[] args) { 3 | // java.util.Enumeration 4 | // boolean hasMoreElements() 5 | // E nextElement() 6 | 7 | 8 | // java.util.Hashtable 9 | // Enumeration keys() 10 | // Enumeration elements() 11 | 12 | 13 | // java.util.Vector 14 | // Enumeration elements() 15 | } 16 | } -------------------------------------------------------------------------------- /src/第7章异常断言和日志/7.4使用断言/ClassLoaderAPI.java: -------------------------------------------------------------------------------- 1 | public class ClassLoaderAPI { 2 | public static void main(String[] args) { 3 | // java.lang.ClassLoader 4 | // void setDefaultAssertionStatus(boolean b) 5 | 6 | // void setClassAssertionStatus(String className, boolean b) 7 | 8 | // void setPackageAssertionStatus(String packageName, boolean b) 9 | 10 | // void clearAssertionStatus 11 | // 移除所有类和包的显示断言状态 12 | } 13 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.6字符串/StringJoin.java: -------------------------------------------------------------------------------- 1 | public class StringJoin { 2 | public static void main(String[] args) { 3 | String all = String.join(" / ", "S", "M", "L", "XL", "XXL"); 4 | print(all); 5 | all = String.join("", "S", "M", "L", "XL", "XXL"); 6 | print(all); 7 | all = String.join(" / "); 8 | print(all); 9 | all = String.join(" / ", "S"); 10 | print(all); 11 | } 12 | static void print(String s) { 13 | System.out.println("\"" + s + "\""); 14 | } 15 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.8控制流程/FallThroughTest.java: -------------------------------------------------------------------------------- 1 | public class FallThroughTest { 2 | @SuppressWarnings("fallthrough") 3 | public static void main(String[] args) { 4 | int n = 2; 5 | int m = -1; 6 | switch (n) 7 | { 8 | case 1: 9 | m = 1; 10 | break; 11 | case 2: 12 | m = 2; 13 | // break; 14 | case 3: 15 | m = 3; 16 | // break; 17 | //default: 18 | // m = 4; 19 | } 20 | System.out.println(m); 21 | } 22 | } -------------------------------------------------------------------------------- /src/第5章继承/5.1类超类和子类/inharitance/Manager.java: -------------------------------------------------------------------------------- 1 | public class Manager extends Employee { 2 | private double bonus; 3 | 4 | public Manager(String name, double salary, int year, int month, int day) { 5 | super(name, salary, year, month, day); 6 | bonus = 0; 7 | } 8 | 9 | void setBonus(double bonus) { 10 | this.bonus = bonus; 11 | } 12 | 13 | public double getSalary() { 14 | return super.getSalary() + bonus; 15 | } 16 | } -------------------------------------------------------------------------------- /src/第9章集合/9.5算法/ShuffleTest.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class ShuffleTest { 4 | public static void main(String[] args) { 5 | List numbers = new ArrayList<>(); 6 | for(int i = 0; i <= 49; i++) 7 | numbers.add(i); 8 | Collections.shuffle(numbers); 9 | List winningCombination = numbers.subList(0, 6); 10 | Collections.sort(winningCombination); 11 | System.out.println(winningCombination); 12 | } 13 | } -------------------------------------------------------------------------------- /src/第9章集合/9.6遗留的集合/BitSetAPI.java: -------------------------------------------------------------------------------- 1 | public class BitSetAPI { 2 | public static void main(String[] args) { 3 | // java.util.BitSet 4 | // BitSet(int initialCapacity) 5 | // int length() 6 | // boolean get(int bit) 7 | // void set(int bit) 8 | // void clear(int bit) 9 | // void and(BitSet set) 10 | // void or(BitSet set) 11 | // void xor(BitSet set) 12 | 13 | // void andNot(BitSet set) 14 | // 清除这个位集中对应另一个位集设置的所有位 15 | } 16 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.7输入输出/IOTest.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | import java.io.*; 3 | import java.nio.file.*; 4 | public class IOTest { 5 | public static void main(String[] args) throws IOException { 6 | Scanner in = new Scanner(Paths.get("inFile.txt"), "UTF-8"); 7 | PrintWriter ot = new PrintWriter("outFile.txt", "UTF-8"); 8 | 9 | while(in.hasNext()) 10 | { 11 | String line = in.nextLine(); 12 | System.out.println(line); 13 | ot.println(line); 14 | System.out.println(line); 15 | } 16 | 17 | ot.close(); // 需要关闭 不然文件里没东西 18 | } 19 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.9大数值/BigDecimalAPI.java: -------------------------------------------------------------------------------- 1 | public class BigDecimalAPI { 2 | public static void main(String[] args) { 3 | // BigDecimal add(BigDecimal other) 4 | // BigDecimal subtract(BigDecimal other) 5 | // BigDecimal multiply(BigDecimal other) 6 | // BigDecimal divide(BigDecimal other, RoundingMode mode) 7 | // 计算商要给出舍入模式,常见的四舍五入 RoundingMode.HALF_UP 8 | 9 | // int compareTo(BigDecimal other) 10 | 11 | // static BigDecimal valueOf(long x) 12 | // static BigDecimal valueOf(long x, int scale) 13 | // 返回 x / (10 ^ scale) 14 | } 15 | } -------------------------------------------------------------------------------- /src/第5章继承/5.2Object所有类的超类/ClassAPI.java: -------------------------------------------------------------------------------- 1 | public class ClassAPI { 2 | public static void main(String[] args) { 3 | // java.lang.Object 4 | // Class getCalss() 5 | // 返回类运行时的描述 6 | 7 | // java.lang.Object 8 | // boolean equals(Object otherObject) 9 | 10 | // java.lang.Object 11 | // String toString() 12 | 13 | // java.lang.Class 14 | // String getName() 15 | // 返回类的名字 16 | 17 | // java.lang.Class 18 | // Class getSuperclass() 19 | // 返回超类信息 20 | } 21 | } -------------------------------------------------------------------------------- /src/第5章继承/5.6枚举类/EnumAPI.java: -------------------------------------------------------------------------------- 1 | public class EnumAPI { 2 | public static void main(String[] args) { 3 | // java.lang.Enum 4 | // static Enum valueOf(Class enumClass, String name) 5 | // 返回指定 name 给定 enumClass 的枚举常量 6 | 7 | // static E[] values() 8 | // 返回全部枚举值的数组 9 | 10 | // String toString() 11 | // 返回枚举常量名,去静态 valueOf 互逆 12 | 13 | // int ordinal 14 | // 枚举常量声明时的位置,从 0 开始计数 15 | 16 | // int compareTo(E other) 17 | // 枚举常量出现在 other 之前返回负值,this == other 返回 0,否则返回正值 18 | } 19 | } -------------------------------------------------------------------------------- /src/第9章集合/9.6遗留的集合/PropertiesAPI.java: -------------------------------------------------------------------------------- 1 | public class PropertiesAPI { 2 | public static void main(String[] args) { 3 | // java.util.Properties 4 | // Properties() 5 | // Properties(Properties defaults) 6 | // String getProperty(String key) 7 | 8 | // String getProperty(String key, String defaultValue) 9 | // 没找到 key 对应的属性时 返回 defaultValue 10 | 11 | // void load(InputStream in) 12 | // 从 in 中加载对象 13 | 14 | // void store(OutputStream out, String commentString) 15 | // 把属性映射存到 out 16 | } 17 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.5运算符/ModAndFloorMod.java: -------------------------------------------------------------------------------- 1 | public class ModAndFloorMod { 2 | public static void main(String[] args) { 3 | int a, b; 4 | a = 4; b = 3; f(a,b); 5 | a = -4; b = 3; f(a,b); 6 | a = 4; b = -3; f(a,b); 7 | a = -4; b = -3; f(a,b); 8 | a = 5; b = 3; f(a,b); 9 | a = -5; b = 3; f(a,b); 10 | a = 5; b = -3; f(a,b); 11 | a = -5; b = -3; f(a,b); 12 | } 13 | 14 | static void f(int a, int b) 15 | { 16 | System.out.printf("%2d %% %2d = %2d", a, b, (a % b)); 17 | System.out.printf(", floorMod(%2d, %2d) = %2d\n", a, b, Math.floorMod(a, b)); 18 | } 19 | } -------------------------------------------------------------------------------- /src/第5章继承/5.1类超类和子类/inharitance/ManagerTest.java: -------------------------------------------------------------------------------- 1 | public class ManagerTest { 2 | public static void main(String[] args) { 3 | Manager boss = new Manager("Carl Cracker", 80000, 1987, 12, 15); 4 | boss.setBonus(5000); 5 | Employee[] staff = new Employee[3]; 6 | staff[0] = boss; 7 | staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1); 8 | staff[2] = new Employee("Tommy Tester", 40000, 1990, 3, 15); 9 | 10 | for(Employee e : staff) 11 | System.out.println("name = " + e.getName() + ", salary = " + e.getSalary()); 12 | 13 | } 14 | } -------------------------------------------------------------------------------- /src/第4章对象与类/4.6对象构造/ExplicitInit.java: -------------------------------------------------------------------------------- 1 | public class ExplicitInit { 2 | public static void main(String[] args) { 3 | Employee a = new Employee(); 4 | Employee b = new Employee(); 5 | Employee c = new Employee(); 6 | System.out.println("a id = " + a.getId()); 7 | System.out.println("b id = " + b.getId()); 8 | System.out.println("c id = " + c.getId()); 9 | } 10 | } 11 | class Employee { 12 | private static int nextId = 1; 13 | private int id = assignId(); 14 | private static int assignId() { 15 | return nextId++; 16 | } 17 | 18 | int getId() { 19 | return id; 20 | } 21 | } -------------------------------------------------------------------------------- /src/第5章继承/5.1类超类和子类/inharitance/Employee.java: -------------------------------------------------------------------------------- 1 | import java.time.*; 2 | 3 | public class Employee { 4 | private String name; 5 | private double salary; 6 | private LocalDate hireDay; 7 | public Employee(String n, double s, int year, int month, int day) { 8 | name = n; 9 | salary = s; 10 | hireDay = LocalDate.of(year, month, day); 11 | } 12 | public String getName() { 13 | return name; 14 | } 15 | public double getSalary() { 16 | return salary; 17 | } 18 | public LocalDate getHireDay() { 19 | return hireDay; 20 | } 21 | public void raiseSalary(double byPercent) { 22 | double raise = salary * byPercent / 100; 23 | salary += raise; 24 | } 25 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.10数组/IrragularArray.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class IrragularArray { 3 | public static void main(String[] args) { 4 | int NMAX = 10; 5 | int[][] angle = new int[NMAX + 1][]; 6 | for(int i = 0; i <= NMAX; i++) { 7 | angle[i] = new int[i + 1]; 8 | angle[i][0] = angle[i][i] = 1; 9 | for(int j = 1; j < i; j++) 10 | angle[i][j] = angle[i - 1][j - 1] + angle[i - 1][j]; 11 | } 12 | System.out.println(Arrays.deepToString(angle)); 13 | 14 | System.out.println("\n==============="); 15 | for(int i = 0; i <= NMAX; i++) { 16 | for(int j = 0; j <= i; j++) 17 | System.out.print(angle[i][j] + " "); 18 | System.out.println(); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/第4章对象与类/4.7包/com/mypackage/Employee.java: -------------------------------------------------------------------------------- 1 | package com.mypackage; 2 | 3 | import java.time.*; 4 | 5 | public class Employee { 6 | private String name; 7 | private double salary; 8 | private LocalDate hireDay; 9 | public Employee(String n, double s, int year, int month, int day) { 10 | name = n; 11 | salary = s; 12 | hireDay = LocalDate.of(year, month, day); 13 | } 14 | public String getName() { 15 | return name; 16 | } 17 | public double getSalary() { 18 | return salary; 19 | } 20 | public LocalDate getHireDay() { 21 | return hireDay; 22 | } 23 | public void raiseSalary(double byPercent) { 24 | double raise = salary * byPercent / 100; 25 | salary += raise; 26 | } 27 | } -------------------------------------------------------------------------------- /src/第6章接口lambda表达式与内部类/6.2接口示例/cloneTest/Manager.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class Manager extends Employee { 3 | private double bonus; 4 | private Date chargeDay; 5 | public Manager(String name, double salary, double bonus) { 6 | super(name, salary); 7 | this.bonus = bonus; 8 | chargeDay = new Date(); 9 | } 10 | public void setChargeDay(int year, int month, int day) { 11 | Date newChargeDay = new GregorianCalendar(year, month - 1, day).getTime(); 12 | chargeDay.setTime(newChargeDay.getTime()); 13 | } 14 | public String toString() { 15 | return super.toString() + "[bonus = " + bonus + ", chargeDay = " + chargeDay + "]"; 16 | } 17 | } -------------------------------------------------------------------------------- /src/第5章继承/5.4对象包装器与自动装箱/IntegerAPI.java: -------------------------------------------------------------------------------- 1 | public class IntegerAPI { 2 | public static void main(String[] args) { 3 | // java.lang.Integer 4 | // int intValue() 5 | // int 形式返回值 6 | 7 | // static String toString(int i) 8 | 9 | // static String toString(int i,int radix) 10 | // radix 进制下的 i 11 | 12 | // static int parseInt(String s) 13 | 14 | // static int parseInt(String s, int radix) 15 | // 串是 radix 进制的 16 | 17 | // static Integer valueOf(String s) 18 | // static Integer valueOf(String s, int radix) 19 | 20 | // java.text.NumberFormat 21 | // Number parse(String s) 22 | // 返回数字值 23 | } 24 | } -------------------------------------------------------------------------------- /src/第8章泛型程序设计/8.9反射和泛型/ClassAPI.java: -------------------------------------------------------------------------------- 1 | public class ClassAPI { 2 | public static void main(String[] args) { 3 | // java.lang.Class 4 | // T newInstance() 5 | // 用无参构造器构建一个新的 T 对象 6 | 7 | // T cast(Object obj) 8 | // obj 是 null 或可以转化成 T 的类型则返回 obj 9 | // 否则抛出 BadCastException 异常 10 | 11 | // T[] getEnumConstants() 12 | // 如果 T 是枚举类型(或是枚举值数组),返回所有值组成的数组 13 | 14 | // Class getSuperclass() 15 | // 返回这个类的超类。如果 T 不是一个类或是 Object 类则返回 null 16 | 17 | // Constructor getConstructor(Class... parameterTypes) 18 | // Constructor getDeclaredConstructor(Class... parameterTypes) 19 | // 获得给定参数类型的构造器 20 | } 21 | } -------------------------------------------------------------------------------- /src/第6章接口lambda表达式与内部类/6.5代理/ProxyAPI.java: -------------------------------------------------------------------------------- 1 | public class ProxyAPI { 2 | public static void main(String[] args) { 3 | // java.lang.reflect.InvocationHandler 4 | // Object invoke(Object proxy, Mehtod method, Object[] args) 5 | // 定义了代理对象调用方法时希望执行的操作 6 | 7 | // java.lang.reflect.Proxy 8 | // static Class getProxyClass(ClassLoader loader, Class... interfaces) 9 | // 返回实现指定接口的代理类 10 | 11 | // static Object newProxyInstance(ClassLoader loader, Class[] interface, InvocationHandler handler) 12 | // 构造实现指定接口的代理类的一个实例 13 | // 所有方法都会调用给定处理器对象的 invoke 方法 14 | 15 | // static boolean isProxyClass(Class cl) 16 | // cl 是代理类则返回 true 17 | } 18 | } -------------------------------------------------------------------------------- /src/第9章集合/9.2具体的集合/PriorityQueueTest.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | import java.time.*; 3 | 4 | public class PriorityQueueTest { 5 | public static void main(String[] args) { 6 | PriorityQueue pq = new PriorityQueue<>(); 7 | pq.add(LocalDate.of(1906, 12, 9)); 8 | pq.add(LocalDate.of(1815, 12, 10)); 9 | pq.add(LocalDate.of(1903, 12, 3)); 10 | pq.add(LocalDate.of(1910, 6, 22)); 11 | 12 | System.out.println("Iterating over elements ..."); 13 | for(LocalDate date : pq) 14 | System.out.print(date + " "); 15 | System.out.println("\nRemoving elements ..."); 16 | while(!pq.isEmpty()) 17 | System.out.print(pq.remove() + " "); 18 | } 19 | } -------------------------------------------------------------------------------- /src/第6章接口lambda表达式与内部类/6.3lambda表达式/MethodReferenceTest.java: -------------------------------------------------------------------------------- 1 | import java.awt.*; 2 | import java.awt.event.*; 3 | import java.util.*; 4 | import javax.swing.*; 5 | import javax.swing.Timer; 6 | 7 | public class MethodReferenceTest { 8 | public static void main(String[] args) { 9 | TimedGreeter obj = new TimedGreeter(); 10 | obj.greet(); 11 | } 12 | } 13 | class Greeter { 14 | public void greet(ActionEvent e) { 15 | System.out.println("Hello, world!"); 16 | } 17 | } 18 | class TimedGreeter extends Greeter { 19 | public void greet() { 20 | Timer t = new Timer(1000, super::greet); 21 | t.start(); 22 | JOptionPane.showMessageDialog(null, "Quit program?"); 23 | System.exit(0); 24 | } 25 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.6字符串/StringBuilderAPI.java: -------------------------------------------------------------------------------- 1 | public class StringBuilderAPI { 2 | public static void main(String[] args) { 3 | // StringBuilder() 空串构造器 4 | 5 | // int length() 构造器或缓冲器中代码单元数量 6 | 7 | // StringBuilder append(String str) 8 | // StringBuilder append(char c) 9 | // StringBuilder appendCodePoint(int cp) 10 | // 追加并返回 this 11 | 12 | // void setCharAt(int i, char c) 13 | // 将第 i 个代码单元替换为 c 14 | 15 | // StringBuilder insert(int offset, String str) 16 | // StringBuilder insert(int offset, char c) 17 | // offset 位置插入字符串 str 或 c 并返回 this 18 | 19 | // StringBuilder delete(int startIndex, int endIndex) 20 | // 删除 [startIndex, endIndex) 的代码单元,返回this 21 | 22 | // String toString() 23 | // 返回与构建器或缓冲器相同的字符串 24 | 25 | } 26 | } -------------------------------------------------------------------------------- /src/第5章继承/5.2Object所有类的超类/HashCodeAPI.java: -------------------------------------------------------------------------------- 1 | public class HashCodeAPI { 2 | public static void main(String[] args) { 3 | // java.util.Object 4 | // int hashCode() 5 | 6 | // java.util.Objects 7 | // static int hash(Object... objects) 8 | // 返回一个散列码 由所有对象的散列码组合而成(为所有对象调用下面的hashCode) 9 | 10 | // java.util.Objects 11 | // static int hashCode(Object a) 12 | // 如果 a 是 null 返回 0 否则返回 a.hashCode() 13 | 14 | // java.lang.(Integer|Long|Short|Byte|Double|Float|Character|Boolean) 15 | // static int hashCode((int|long|short|byte|double|float|char|boolean) value) 16 | // 返回给定基本类型值的散列码 17 | 18 | // java.util.Arrays 19 | // static int hashCode(type[] a) 20 | // 返回 a 数组的散列码 21 | } 22 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.6字符串/StringEqual.java: -------------------------------------------------------------------------------- 1 | public class StringEqual { 2 | public static void main(String[] args) { 3 | String a = "Hello", b = "hello"; 4 | String c = "hello"; 5 | System.out.println("a == b : " + (a == b)); 6 | System.out.println("b == c : " + (b == c)); 7 | System.out.println("a.equals(b) : " + (a.equals(b))); 8 | System.out.println("b.equals(c) : " + (b.equals(c))); 9 | System.out.println("\"hello\".equals(b) : " + ("hello".equals(b))); 10 | System.out.println("\"hello\" == b : " + ("hello" == b)); 11 | 12 | System.out.println("b.substring(0, 3) : " + b.substring(0, 3)); 13 | System.out.println("\"hel\" == b.substring(0, 3) : " + ("hel" == b.substring(0, 3))); 14 | 15 | System.out.println("a.equalsIgnoreCase(b) : " + (a.equalsIgnoreCase(b))); 16 | } 17 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.10数组/LotteryDrawing.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class LotteryDrawing { 3 | public static void main(String[] args) { 4 | Scanner in = new Scanner(System.in); 5 | 6 | // generate k elements permutation form [1, n] 7 | System.out.print("Number to draw: "); 8 | int k = in.nextInt(); 9 | 10 | System.out.print("Highest number: "); 11 | int n = in.nextInt(); 12 | 13 | int[] nums = new int[n]; 14 | for(int i = 0; i < n; i++) 15 | nums[i] = i + 1; 16 | 17 | int[] res = new int[k]; 18 | for(int i = 0; i < k; i++) { 19 | int r = (int)(Math.random() * n); 20 | res[i] = nums[r]; 21 | 22 | // remove nums[r] 23 | nums[r] = nums[n - 1]; 24 | n--; 25 | } 26 | 27 | Arrays.sort(res); // 排序 28 | System.out.println(Arrays.toString(res)); 29 | } 30 | } -------------------------------------------------------------------------------- /src/第7章异常断言和日志/7.2捕获异常/StackTraceTest.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class StackTraceTest { 4 | public static void main(String[] args) { 5 | //Scanner in = new Scanner(System.in); 6 | //System.out.println("Enter n : "); 7 | //int n = in.nextInt(); 8 | int n = 5; 9 | factorial(n); 10 | } 11 | public static int factorial(int n) { 12 | System.out.println("factorial(" + n + ") : "); 13 | Throwable t = new Throwable(); 14 | StackTraceElement[] frames = t.getStackTrace(); 15 | for(StackTraceElement f : frames) 16 | System.out.println(f); 17 | int r; 18 | if(n <= 1) r = 1; 19 | else r = n * factorial(n - 1); 20 | System.out.println("return " + r); 21 | return r; 22 | } 23 | } -------------------------------------------------------------------------------- /src/第5章继承/5.1类超类和子类/abstractClasses/Employee.java: -------------------------------------------------------------------------------- 1 | import java.time.*; 2 | 3 | public class Employee extends Person{ 4 | // private String name; 5 | private double salary; 6 | private LocalDate hireDay; 7 | public Employee(String name, double salary, int year, int month, int day) { 8 | super(name); 9 | this.salary = salary; 10 | hireDay = LocalDate.of(year, month, day); 11 | } 12 | // public String getName() { 13 | // return name; 14 | // } 15 | public double getSalary() { 16 | return salary; 17 | } 18 | public LocalDate getHireDay() { 19 | return hireDay; 20 | } 21 | public String getDescription() { 22 | return String.format("An employee with a salary of $%.2f", salary); 23 | } 24 | public void raiseSalary(double byPercent) { 25 | double raise = salary * byPercent / 100; 26 | salary += raise; 27 | } 28 | } -------------------------------------------------------------------------------- /notes/Java核心技术卷一0.md: -------------------------------------------------------------------------------- 1 | # 《Java核心技术卷一》 笔记 0 2 | 3 | 2019.06.4 16:25 4 | 5 | 6 | 7 | ## 前言 8 | 9 | ### 两卷内容组织 10 | 11 | 卷一: 12 | 13 | 面向对象程序设计 14 | 15 | 反射与代理 16 | 17 | 接口和内部类 18 | 19 | 异常处理 20 | 21 | 泛型程序设计 22 | 23 | 集合框架 24 | 25 | 事件监听器模型 26 | 27 | Swing UI 工具箱 28 | 29 | 并行操作 30 | 31 | 32 | 33 | 卷二: 34 | 35 | 流 API 36 | 37 | ‘文件处理与正则表达式 38 | 39 | 数据库 40 | 41 | XML 处理 42 | 43 | 注释 44 | 45 | 国际化 46 | 47 | 网络编程 48 | 49 | 高级 GUI 组件 50 | 51 | 高级图形 52 | 53 | 原生方法 54 | 55 | 56 | 57 | ### 本书内容组织 58 | 59 | 第一章:Java 与其他语言对比,Java 诞生与发展 60 | 61 | 第二章:下载安装编译运行 62 | 63 | 第三章:变量,循环,函数 64 | 65 | 第四章:OOP 66 | 67 | 第五章:继承 68 | 69 | 第六章:Java接口,lambda表达式,内部类 70 | 71 | 第七章:异常处理,调试技巧 72 | 73 | 第八章:泛型 74 | 75 | 第九章:集合框架 76 | 77 | 第十章:GUI 78 | 79 | 第十一章:AWT 80 | 81 | 第十二章:GUI 82 | 83 | 第十三章:部署为应用或 applet,打包 jar 包 84 | 85 | 第十四章:并发 86 | 87 | -------------------------------------------------------------------------------- /src/第9章集合/9.5算法/SortShuffleAPI.java: -------------------------------------------------------------------------------- 1 | public class SortShuffleAPI { 2 | public static void main(String[] args) { 3 | // java.util.Collections 4 | // static > void sort(List elements) 5 | // 稳定排序 nlogn 复杂度 6 | 7 | // static void shuffle(List elements) 8 | // static void shuffle(List elements, Random r) 9 | // 随机打乱元素,时间复杂度 n*a(n), a(n)是元素平均访问时间 10 | 11 | 12 | // java.util.List 13 | // default void sort(Comparator comparator) 14 | // 用给定比较器给列表排序 15 | 16 | 17 | // java.util.Comparator 18 | // static > Comparator reverseOrder() 19 | // 生成一个比较器,逆置 Comparable 的顺序 20 | 21 | // default Compartor reversed() 22 | // 逆置这个比较器的顺序 23 | } 24 | } -------------------------------------------------------------------------------- /src/第4章对象与类/4.6对象构造/CallAnotherConstructor.java: -------------------------------------------------------------------------------- 1 | public class CallAnotherConstructor { 2 | public static void main(String[] args) { 3 | Employee a = new Employee("Alice", 50000); 4 | Employee b = new Employee(60000); 5 | a.print(); 6 | b.print(); 7 | } 8 | } 9 | class Employee { 10 | static int nextId = 1; 11 | 12 | private String name; 13 | private double salary; 14 | private int id; 15 | 16 | Employee(String name, double salary) { 17 | this.name = name; 18 | this.salary = salary; 19 | this.id = nextId++; 20 | } 21 | 22 | Employee(double salary) { 23 | this("Employee #" + nextId, salary); 24 | } 25 | 26 | public void print() { 27 | System.out.println("name = " + name + ", salary = " + salary 28 | + ", id = " + id); 29 | } 30 | } -------------------------------------------------------------------------------- /src/第4章对象与类/4.2使用预定义类/DateAndLocalDate.java: -------------------------------------------------------------------------------- 1 | import java.util.*; // Date 2 | import java.time.*; // LocalDate 3 | 4 | public class DateAndLocalDate { 5 | public static void main(String[] args) { 6 | Date birthday = new Date(); 7 | System.out.println("Date : " + birthday); 8 | 9 | LocalDate nowLocalDate = LocalDate.now(); 10 | LocalDate oldLocalDate = LocalDate.of(1966,1,1); 11 | System.out.println("nowLocalDate : " + nowLocalDate); 12 | System.out.println("oldLocalDate : " + oldLocalDate); 13 | 14 | System.out.println("now year : " + nowLocalDate.getYear()); 15 | System.out.println("now month : " + nowLocalDate.getMonth()); 16 | System.out.println("now month value : " + nowLocalDate.getMonthValue()); 17 | System.out.println("now day of month : " + nowLocalDate.getDayOfMonth()); 18 | System.out.println("now day of year : " + nowLocalDate.getDayOfYear()); 19 | } 20 | } -------------------------------------------------------------------------------- /src/第5章继承/5.3泛型数组列表/ArrayListAPI.java: -------------------------------------------------------------------------------- 1 | 2 | public class ArrayListAPI { 3 | public static void main(String[] args) { 4 | // java.util.ArrayList 5 | // ArrayList() 6 | 7 | // ArrayList(int initialCapacity) 8 | // 列表的初始容量 9 | 10 | // boolean add(E obj) 11 | // 尾部添加元素 12 | 13 | // int size() 14 | // 返回当前元素数量(小于等于数组列表容量) 15 | 16 | // void ensureCapacity(int capacity) 17 | // 确保不重新分配存储空间的元素数量 18 | 19 | // void trimToSize() 20 | // 将容量减到当前元素个数 21 | 22 | // void set(int index, E obj) 23 | // index 在[0, size() - 1] 24 | // 替换原有位置的元素 25 | 26 | // E get(int index) 27 | 28 | // void add(int index, E obj) 29 | // index 在[0, size() - 1] 30 | 31 | // E remove(int indx) 32 | // index 在[0, size() - 1] 33 | // 返回被删除元素 34 | } 35 | } -------------------------------------------------------------------------------- /src/第6章接口lambda表达式与内部类/6.2接口示例/TimerTest.java: -------------------------------------------------------------------------------- 1 | import java.awt.*; 2 | import java.awt.event.*; 3 | import java.util.*; 4 | import javax.swing.*; 5 | import javax.swing.Timer;// conflict with java.util.Timer 6 | 7 | public class TimerTest { 8 | public static void main(String[] args) { 9 | ActionListener listener = new TimePrinter(); 10 | 11 | Timer t = new Timer(1000, listener); // 1000 ms interval 12 | t.start(); 13 | // start() start Timer 14 | // end() end Timer 15 | JOptionPane.showMessageDialog(null, "Quit program?"); 16 | // block 17 | System.exit(0); 18 | } 19 | } 20 | class TimePrinter implements ActionListener { 21 | public void actionPerformed(ActionEvent event) { 22 | System.out.println("At the tone, the time is " + new Date()); 23 | //Toolkit.getDefaultToolkit().beep(); 24 | // beep sound 25 | } 26 | } -------------------------------------------------------------------------------- /src/第5章继承/5.6枚举类/EnumTest.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class EnumTest { 3 | public static void main(String[] args) { 4 | Scanner in = new Scanner(System.in); 5 | System.out.print("Enter a size: (SMALL, MEDIUM, LARGE, EXTRA_LARGE) "); 6 | String input = in.next().toUpperCase(); 7 | Size size = Enum.valueOf(Size.class, input); 8 | System.out.println("size = " + size); 9 | System.out.println("abbreviation = " + size.getAbbreviation()); 10 | if(size == Size.EXTRA_LARGE) 11 | System.out.println("Good Job"); 12 | } 13 | } 14 | 15 | enum Size { 16 | SMALL("S"), MEDIUM("M"), LARGE("L"), EXTRA_LARGE("XL"); 17 | 18 | private String abbreviation; 19 | 20 | private Size(String abbreviation) { 21 | this.abbreviation = abbreviation; 22 | } 23 | public String getAbbreviation() { 24 | return abbreviation; 25 | } 26 | } -------------------------------------------------------------------------------- /src/第9章集合/9.2具体的集合/SetTest.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class SetTest { 4 | public static void main(String[] args) { 5 | Set words = new HashSet<>(); 6 | long totalTime = 0; 7 | 8 | try (Scanner in = new Scanner(System.in)) { 9 | while(in.hasNext()) { 10 | String word = in.next(); 11 | long callTime = System.currentTimeMillis(); 12 | words.add(word); 13 | callTime = System.currentTimeMillis() - callTime; 14 | totalTime += callTime; 15 | } 16 | } 17 | 18 | Iterator iter = words.iterator(); 19 | for(int i = 1; i <= 20 && iter.hasNext(); i++) { 20 | System.out.println(iter.next()); 21 | } 22 | System.out.println("..."); 23 | System.out.println(words.size() + " distinct words.\n" + totalTime + " ms"); 24 | } 25 | } -------------------------------------------------------------------------------- /src/第4章对象与类/4.2使用预定义类/CalendarTest.java: -------------------------------------------------------------------------------- 1 | import java.time.*; 2 | public class CalendarTest { 3 | public static void main(String[] args) { 4 | LocalDate date = LocalDate.now(); 5 | int month = date.getMonthValue(); 6 | int today = date.getDayOfMonth(); 7 | 8 | date = date.minusDays(today - 1); 9 | DayOfWeek weekday = date.getDayOfWeek; 10 | int value = weekday.getValue(); 11 | 12 | System.out.println("Mon Tue Wed Thu Fri Sat Sun"); 13 | for(int i = 1; i < value; i++) 14 | System.out.print(" "); 15 | 16 | while(date.getMonthValue() == month) 17 | { 18 | System.out.printf("%3d", date.getDayOfMonth()); 19 | if(date.getDayOfMonth() == today) 20 | System.out.print("*"); 21 | else 22 | System.out.print(" "); 23 | date = date.plusDays(1); 24 | if(date.getDayOfWeek().getValue() == 1) 25 | System.out.println(); 26 | } 27 | if(date.getDayOfWeek().getValue() != 1) 28 | System.out.println(); 29 | } 30 | } -------------------------------------------------------------------------------- /src/第6章接口lambda表达式与内部类/6.4内部类/AnonymousInnerClassTest.java: -------------------------------------------------------------------------------- 1 | import java.awt.*; 2 | import java.awt.event.*; 3 | import java.util.*; 4 | import javax.swing.*; 5 | import javax.swing.Timer; 6 | 7 | public class AnonymousInnerClassTest { 8 | public static void main(String[] args) { 9 | TalkingClock clock = new TalkingClock(); 10 | clock.start(1000, false); 11 | JOptionPane.showMessageDialog(null, "Quit Program?"); 12 | System.exit(0); 13 | } 14 | } 15 | class TalkingClock { 16 | public void start(int interval, boolean beep) { 17 | ActionListener listener = new ActionListener(){ 18 | @Override 19 | public void actionPerformed(ActionEvent e) { 20 | System.out.println("Time " + new Date()); 21 | if(beep) Toolkit.getDefaultToolkit().beep(); 22 | } 23 | }; 24 | Timer t = new Timer(interval, listener); 25 | t.start(); 26 | } 27 | } -------------------------------------------------------------------------------- /src/第9章集合/9.6遗留的集合/Sieve.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class Sieve { 4 | public static void main(String[] args) { 5 | int n=2_000_000; 6 | long start = System.currentTimeMillis(); 7 | BitSet b = new BitSet(n + 1); 8 | int count = 0; 9 | int i; 10 | for(i = 2; i <= n; i++) 11 | b.set(i); 12 | i = 2; 13 | while(i * i <= n) { 14 | if(b.get(i)) { 15 | count++; 16 | int k = 2 * i; 17 | while(k <= n) { 18 | b.clear(k); 19 | k += i; 20 | } 21 | } 22 | i++; 23 | } 24 | while(i <= n) { 25 | if(b.get(i)) count++; 26 | i++; 27 | } 28 | long end = System.currentTimeMillis(); 29 | System.out.println("primes : " + count); 30 | System.out.println((end - start) + " ms"); 31 | } 32 | } -------------------------------------------------------------------------------- /src/第5章继承/5.2Object所有类的超类/EqualsTest/Manager.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class Manager extends Employee { 3 | private double bonus; 4 | 5 | public Manager(String name, double salary, int year, int month, int day) { 6 | super(name, salary, year, month, day); 7 | bonus = 0; 8 | } 9 | 10 | void setBonus(double bonus) { 11 | this.bonus = bonus; 12 | } 13 | 14 | public double getSalary() { 15 | return super.getSalary() + bonus; 16 | } 17 | 18 | @Override 19 | public boolean equals(Object otherObject) { 20 | if(!super.equals(otherObject)) return false; 21 | Manager other = (Manager)otherObject; 22 | return bonus == other.bonus; 23 | } 24 | 25 | public int hashCode() { 26 | return super.hashCode() + 17 * Double.hashCode(bonus); 27 | } 28 | 29 | public String toString() { 30 | return super.toString() + "[bonus=" + bonus + "]"; 31 | } 32 | } -------------------------------------------------------------------------------- /src/第5章继承/5.7反射/MethodTableTest.java: -------------------------------------------------------------------------------- 1 | import java.lang.reflect.*; 2 | 3 | public class MethodTableTest { 4 | public static void main(String[] args) throws Exception { 5 | Method square = MethodTableTest.class.getMethod("square", double.class); 6 | Method sqrt = Math.class.getMethod("sqrt", double.class); 7 | 8 | printTable(1, 10, 10, square); 9 | printTable(1, 10, 10, sqrt); 10 | } 11 | public static double square(double x) { 12 | return x * x; 13 | } 14 | public static void printTable(double from, double to, int n, Method f) { 15 | double dx = (to - from) / (n - 1); 16 | 17 | for(double x = from; x <= to; x += dx) { 18 | try { 19 | double y = (Double) f.invoke(null, x); 20 | System.out.printf("%10.4f | %10.4f\n", x , y); 21 | } catch (Exception e) { 22 | e.printStackTrace(); 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/第6章接口lambda表达式与内部类/6.4内部类/InnerClassLocalParam.java: -------------------------------------------------------------------------------- 1 | import java.awt.*; 2 | import java.awt.event.*; 3 | import java.util.*; 4 | import javax.swing.*; 5 | import javax.swing.Timer; 6 | 7 | public class InnerClassLocalParam { 8 | public static void main(String[] args) { 9 | TalkingClock clock = new TalkingClock(); 10 | clock.start(1000, false); 11 | JOptionPane.showMessageDialog(null, "Quit Program?"); 12 | System.exit(0); 13 | } 14 | } 15 | class TalkingClock { 16 | public void start(int interval, boolean beep) { 17 | class TimePrinter implements ActionListener { 18 | public void actionPerformed(ActionEvent event) { 19 | System.out.println("Time " + new Date()); 20 | if(beep) Toolkit.getDefaultToolkit().beep(); 21 | } 22 | } 23 | ActionListener listener = new TimePrinter(); 24 | Timer t = new Timer(interval, listener); 25 | t.start(); 26 | } 27 | } -------------------------------------------------------------------------------- /src/第8章泛型程序设计/8.5泛型代码和虚拟机/BridgeMethodTest2.java: -------------------------------------------------------------------------------- 1 | public class BridgeMethodTest2 { 2 | public static void main(String[] args) throws CloneNotSupportedException { 3 | Employee e = new Employee("Alice", 20000); 4 | Employee e2 = e.clone(); 5 | e2.setSalary(50000); 6 | e.print(); 7 | e2.print(); 8 | } 9 | } 10 | class Employee implements Cloneable { 11 | private String name; 12 | private double salary; 13 | public Employee() {} 14 | public Employee(String name, double salary) { 15 | this.name = name; 16 | this.salary = salary; 17 | } 18 | public void setSalary(double salary) { 19 | this.salary = salary; 20 | } 21 | public void print() { 22 | System.out.println("name = " + name + ", salary = " + salary); 23 | } 24 | public Employee clone() throws CloneNotSupportedException { 25 | Employee e = (Employee) super.clone(); 26 | System.out.println("Employee.clone"); 27 | return e; 28 | } 29 | } -------------------------------------------------------------------------------- /src/第6章接口lambda表达式与内部类/6.3lambda表达式/LambdaTest.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | import javax.swing.*; 3 | import javax.swing.Timer; 4 | 5 | public class LambdaTest { 6 | public static void main(String[] args) { 7 | String[] planets = new String[]{ 8 | "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"}; 9 | System.out.println(Arrays.toString(planets)); 10 | 11 | System.out.println("Sorted in dictionary order: "); 12 | Arrays.sort(planets); 13 | System.out.println(Arrays.toString(planets)); 14 | 15 | System.out.println("Sorted by length: "); 16 | Arrays.sort(planets, (first, second) -> first.length() - second.length()); 17 | System.out.println(Arrays.toString(planets)); 18 | 19 | Timer t = new Timer(1000, event -> System.out.println("The time is " + new Date())); 20 | t.start(); 21 | 22 | JOptionPane.showMessageDialog(null, "Quit program?"); 23 | System.exit(0); 24 | } 25 | } -------------------------------------------------------------------------------- /src/第6章接口lambda表达式与内部类/6.1接口/EmployeeSortTest.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class EmployeeSortTest { 4 | public static void main(String[] args) { 5 | Employee[] staff = new Employee[3]; 6 | staff[0] = new Employee("Harry Hacker", 35000); 7 | staff[1] = new Employee("Carl Cracker", 75000); 8 | staff[2] = new Employee("Tony Tester", 38000); 9 | 10 | Arrays.sort(staff); 11 | 12 | for(Employee e : staff) { 13 | e.print(); 14 | } 15 | } 16 | } 17 | 18 | class Employee implements Comparable { 19 | private String name; 20 | private double salary; 21 | 22 | public Employee(String name, double salary) { 23 | this.name = name; 24 | this.salary = salary; 25 | } 26 | 27 | public void print() { 28 | System.out.println("name = " + name + ", salary = " + salary); 29 | } 30 | 31 | public int compareTo(Employee other) { 32 | return Double.compare(salary, other.salary); 33 | } 34 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.6字符串/CodePoint.java: -------------------------------------------------------------------------------- 1 | public class CodePoint { 2 | public static void main(String[] args) { 3 | String s = "abc\ud836\udd46gg"; 4 | System.out.println(s); 5 | System.out.println(s.length()); // 代码单元长度 6 | System.out.println(s.codePointCount(0,s.length())); 7 | // 码点数量 8 | 9 | int i = 5; 10 | System.out.println(s.charAt(0)); // 第0个代码单元 11 | 12 | i = 4; // 获取第i个码点 13 | int idx = s.offsetByCodePoints(0, i); 14 | System.out.println(s.codePointAt(idx)); 15 | 16 | // 遍历字符串的每个码点 17 | System.out.println("=============="); 18 | for(int j = 0; j < s.length(); j++) { 19 | System.out.print(s.codePointAt(j) + " "); 20 | int cp = s.codePointAt(j); 21 | if(Character.isSupplementaryCodePoint(cp)) 22 | j++; 23 | } 24 | 25 | /* 26 | // 回退 27 | i--; 28 | if(Character.isSurrogate(s.charAt(i))) i--; 29 | int cp = s.codePointAt(); 30 | */ 31 | 32 | // 生成码点数组 33 | int[] codePoints = s.codePoints().toArray(); 34 | 35 | // 从码点数组生成串 36 | String ss = new String(codePoints, 0, codePoints.length); 37 | } 38 | } -------------------------------------------------------------------------------- /src/第8章泛型程序设计/8.6约束与局限性/ErasedCheckedTest.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | import java.io.*; 3 | 4 | public class ErasedCheckedTest { 5 | public static void main(String[] args) { 6 | new Block() { 7 | public void body() throws Exception { 8 | Scanner in = new Scanner(new File("ququx"), "UTF-8"); 9 | while(in.hasNext()) 10 | System.out.println(in); 11 | } 12 | }.toThread().start(); 13 | } 14 | } 15 | 16 | abstract class Block { 17 | public abstract void body() throws Exception; 18 | public Thread toThread() { 19 | return new Thread() { 20 | public void run() { 21 | try { 22 | body(); 23 | } catch (Throwable t) { 24 | Block.throwAs(t); 25 | } 26 | } 27 | }; 28 | } 29 | @SuppressWarnings("unchecked") 30 | public static void throwAs(Throwable e) throws T { 31 | throw (T) e; 32 | } 33 | } -------------------------------------------------------------------------------- /src/第9章集合/9.3映射/MapAPI.java: -------------------------------------------------------------------------------- 1 | public class MapAPI { 2 | public static void main(String[] args) { 3 | // java.util.Map 4 | // V get(Object key) 5 | // default V getOrDefault(Object key, V defaultValue) 6 | 7 | // V put(K key, V value) 8 | // void putAll(Map entries) 9 | 10 | // boolean containsKey(Object key) 11 | // boolean containsValue(Object value) 12 | 13 | // default void forEach(BiConsumer action) 14 | 15 | 16 | // java.util.HashMap 17 | // HashMap() 18 | // HashMap(int initialCapacity) 19 | // HashMap(int initialCapacity, float loadFactor) 20 | 21 | 22 | // java.util.TreeMap 23 | // TreeMap() 24 | // TreeMap(Comparator c) 25 | 26 | // TreeMap(Map entries) 27 | // 使用映射构建 TreeMap 28 | 29 | // TreeMap(SortedMap entries) 30 | // 使用有序映射构建 TreeMap 并使用其比较器 31 | } 32 | } -------------------------------------------------------------------------------- /src/第6章接口lambda表达式与内部类/6.2接口示例/cloneTest/Employee.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class Employee implements Cloneable { 4 | private String name; 5 | private double salary; 6 | private Date hireDay; 7 | public Employee(String n, double s) { 8 | name = n; 9 | salary = s; 10 | hireDay = new Date(); 11 | } 12 | 13 | public void raiseSalary(double byPercent) { 14 | double raise = salary * byPercent / 100; 15 | salary += raise; 16 | } 17 | 18 | public void setHireDay(int year, int month, int day) { 19 | Date newHireDay = new GregorianCalendar(year, month - 1, day).getTime(); 20 | hireDay.setTime(newHireDay.getTime()); 21 | } 22 | 23 | public Employee clone() throws CloneNotSupportedException { 24 | Employee cloned = (Employee) super.clone(); 25 | cloned.hireDay = (Date) hireDay.clone(); 26 | return cloned; 27 | } 28 | 29 | public String toString() { 30 | return "Employee[name = " + name + ", salary = " + salary 31 | + ", hireDay = " + hireDay + "]"; 32 | } 33 | } -------------------------------------------------------------------------------- /src/第9章集合/9.2具体的集合/TreeSetAPI.java: -------------------------------------------------------------------------------- 1 | public class TreeSetAPI { 2 | public static void main(String[] args) { 3 | // java.util.TreeSet 4 | // TreeSet() 5 | // TreeSet(Comparator comparator) 6 | // TreeSet(Collection elements) 7 | // TreeSet(SortedSet s) 8 | 9 | 10 | // java.util.SortedSet 11 | // Comparator comparator() 12 | // 返回对元素排序的比较器 13 | // 使用 Comparable 接口的 compareTo 则返回 null 14 | 15 | // E first() 16 | // E last() 17 | 18 | 19 | // java.util.NavigableSet 20 | // E higher(E value) 21 | // 大于 value 的最小元素 22 | 23 | // E lower(E value) 24 | // 小于 value 的最大元素 25 | 26 | // E ceiling(E value) 27 | // 小于等于 value 的最大元素 28 | 29 | // E floor(E value) 30 | // 大于等于 value 的最小元素 31 | 32 | // E poolFirst() 33 | // E poolLast() 34 | // 删除并返回集中的最大(最小)元素,集为空时返回 null 35 | 36 | // Iterator descendingIterator() 37 | // 递减顺序遍历的迭代器 38 | } 39 | } -------------------------------------------------------------------------------- /src/第9章集合/9.2具体的集合/ListAPI.java: -------------------------------------------------------------------------------- 1 | public class ListAPI { 2 | public static void main(String[] args) { 3 | // java.util.List 4 | // ListIterator listIterator() 5 | // 返回一个列表迭代器 6 | 7 | // ListIterator listIterator(int index) 8 | // 第一次调用 next 将返回 index 的元素 9 | 10 | // void add(int i, E element) 11 | // 在 i 位置新增元素 element 12 | 13 | // void addAll(int i, Collection elements) 14 | // 将某个集合中所有元素添加到给定位置 15 | 16 | // E remove(int i) 17 | 18 | // E get(int i) 19 | 20 | // E set(int i, E element) 21 | // 将给定 i 位置的元素替换并返回原来的元素 22 | 23 | // int indexOf(Object element) 24 | // 返回 element 第一次出现的位置,没有则返回 -1 25 | 26 | // int lastIndexOf(Object element) 27 | // 最后一次出现的位置 28 | 29 | 30 | // java.util.ListIterator 31 | // void add(E newElement) 32 | // void set(E newElement) 33 | // boolean hasPrevious() 34 | // E previous() 35 | // int nextIndex() 36 | // int previousIndex() 37 | } 38 | } -------------------------------------------------------------------------------- /src/第6章接口lambda表达式与内部类/6.4内部类/InnerClassTest.java: -------------------------------------------------------------------------------- 1 | import java.awt.*; 2 | import java.awt.event.*; 3 | import java.util.*; 4 | import javax.swing.*; 5 | import javax.swing.Timer; 6 | 7 | public class InnerClassTest { 8 | public static void main(String[] args) { 9 | TalkingClock clock = new TalkingClock(1000, false); 10 | clock.start(); 11 | JOptionPane.showMessageDialog(null, "Quit Program?"); 12 | System.exit(0); 13 | } 14 | } 15 | class TalkingClock { 16 | private int interval; 17 | private boolean beep; 18 | public TalkingClock(int interval, boolean beep) { 19 | this.interval = interval; 20 | this.beep = beep; 21 | } 22 | public void start() { 23 | ActionListener listener = new TimePrinter(); 24 | Timer t = new Timer(interval, listener); 25 | t.start(); 26 | } 27 | 28 | private class TimePrinter implements ActionListener { 29 | public void actionPerformed(ActionEvent event) { 30 | System.out.println("Time " + new Date()); 31 | if(beep) Toolkit.getDefaultToolkit().beep(); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/第2章Java程序设计环境/2.5 构建并运行applet/RoadApplet.java: -------------------------------------------------------------------------------- 1 | import java.awt.*; 2 | import java.applet.*; 3 | import javax.swing.*; 4 | 5 | public class RoadApplet extends JApplet { 6 | private RoadComonent roadComponent; 7 | private JSlider slowdown; 8 | private JSlider arrival; 9 | 10 | public void init() { 11 | EventQueue.invokeLater(() -> { 12 | roadComponent = new RoadComonent(); 13 | slowdown = new JSlider(0, 100, 10); 14 | arrival = new JSlider(0, 100, 50); 15 | 16 | JPanel p = new JPanel(); 17 | p.setLayout(new GridLayout(1, 6)); 18 | p.add(new JLabel("Slowdown")); 19 | p.add(slowdown); 20 | p.add(new JLabel("")); 21 | p.add(new JLabel("Arrival")); 22 | p.add(arrival); 23 | p.add(new JLabel("")); 24 | setLayout(new BorderLayout()); 25 | add(p, BorderLayout.NORTH); 26 | add(roadComponent, BorderLayout.CENTER); 27 | }); 28 | } 29 | 30 | public void start() { 31 | new Thread(() -> { 32 | for(;;) { 33 | roadComponent.update( 34 | 0.01 * slowdown.getValue(), 35 | 0.01 * arrival.getValue() 36 | ); 37 | try { 38 | Thread.sleep(50); 39 | } catch(InterruptedException e) { 40 | 41 | } 42 | } 43 | }).start(); 44 | } 45 | } -------------------------------------------------------------------------------- /src/第9章集合/9.2具体的集合/QueueAPI.java: -------------------------------------------------------------------------------- 1 | public class QueueAPI { 2 | public static void main(String[] args) { 3 | // java.util.Queue 4 | // boolean add(E element) 5 | // boolean offer(E element) 6 | // 尾部添加元素,并返回 true 7 | // 不能添加时 add 抛出 IllegalStateException 异常,offer 返回 false 8 | 9 | // E remove() 10 | // E poll() 11 | // 删除并返回队首第一个元素 12 | // 队列为空时,remove 抛出 NoSuchElementException 异常,poll 返回 null 13 | 14 | // E element() 15 | // E peek() 16 | // 返回队首第一个元素 17 | // 队列为空时,element 抛出 NoSuchElementException 异常,peek 返回 null 18 | 19 | 20 | // java.util.Deque 21 | // void addFirst(E element) 22 | // void addLast(E element) 23 | // boolean offerFirst(E element) 24 | // boolean offerLast(E element) 25 | 26 | // E removeFirst() 27 | // E removeLast() 28 | // E pollFirst() 29 | // E pollLast() 30 | 31 | // E getFirst() 32 | // E getLast() 33 | // E peekFirst() 34 | // E peekLast() 35 | 36 | // java.util.ArrayDeque 37 | // ArrayDeque() 38 | // ArrayDeque(int initialCapacity) 39 | } 40 | } -------------------------------------------------------------------------------- /src/第6章接口lambda表达式与内部类/6.4内部类/StaticInnerClassTest.java: -------------------------------------------------------------------------------- 1 | public class StaticInnerClassTest { 2 | public static void main(String[] args) { 3 | double[] d = new double[20]; 4 | for(int i = 0; i < d.length; i++) 5 | d[i] = 100 * Math.random(); 6 | ArrayAlg.Pair p = ArrayAlg.minmax(d); 7 | System.out.println("min = " + p.getFirst()); 8 | System.out.println("max = " + p.getSecond()); 9 | } 10 | } 11 | class ArrayAlg { 12 | public static class Pair { 13 | private double first; 14 | private double second; 15 | public Pair(double f, double s) { 16 | first = f; 17 | second = s; 18 | } 19 | public double getFirst() { 20 | return first; 21 | } 22 | public double getSecond() { 23 | return second; 24 | } 25 | } 26 | public static Pair minmax(double[] values) { 27 | double min = Double.POSITIVE_INFINITY; 28 | double max = Double.NEGATIVE_INFINITY; 29 | for(double v : values) 30 | { 31 | if(min > v) min = v; 32 | if(max < v) max = v; 33 | } 34 | return new Pair(min, max); 35 | } 36 | } -------------------------------------------------------------------------------- /src/第9章集合/9.2具体的集合/LinkedListTest.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class LinkedListTest { 4 | public static void main(String[] args) { 5 | List a = new LinkedList<>(); 6 | a.add("Amy"); 7 | a.add("Carl"); 8 | a.add("Erica"); 9 | 10 | List b = new LinkedList<>(); 11 | b.add("Bob"); 12 | b.add("Doug"); 13 | b.add("Frances"); 14 | b.add("Gloria"); 15 | 16 | ListIterator aIter = a.listIterator(); 17 | Iterator bIter = b.iterator(); 18 | 19 | System.out.println("org a = " + a); 20 | System.out.println("org b = " + b); 21 | 22 | while(bIter.hasNext()) { 23 | if(aIter.hasNext()) aIter.next(); 24 | aIter.add(bIter.next()); 25 | } 26 | 27 | System.out.println(a); 28 | 29 | bIter = b.iterator(); 30 | while(bIter.hasNext()) { 31 | bIter.next(); 32 | if(bIter.hasNext()) { 33 | bIter.next(); 34 | bIter.remove(); 35 | } 36 | } 37 | System.out.println(b); 38 | 39 | a.removeAll(b); 40 | 41 | System.out.println(a); 42 | } 43 | } -------------------------------------------------------------------------------- /src/第4章对象与类/4.3用户自定义类/EmployeeTest.java: -------------------------------------------------------------------------------- 1 | import java.time.*; 2 | 3 | public class EmployeeTest 4 | { 5 | public static void main(String[] args) { 6 | Employee[] staff = new Employee[3]; 7 | 8 | staff[0] = new Employee("Carl Cracker", 75000, 1987, 12, 15); 9 | staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1); 10 | staff[2] = new Employee("Tony Tester", 40000, 1990, 3, 15); 11 | 12 | for(Employee e : staff) 13 | e.raiseSalary(5); 14 | 15 | for(Employee e : staff) 16 | System.out.println("name=" + e.getName() + ", salary=" + e.getSalary() 17 | + ", hireDay=" + e.getHireDay()); 18 | } 19 | } 20 | 21 | class Employee { 22 | private String name; 23 | private double salary; 24 | private LocalDate hireDay; 25 | public Employee(String n, double s, int year, int month, int day) { 26 | name = n; 27 | salary = s; 28 | hireDay = LocalDate.of(year, month, day); 29 | } 30 | public String getName() { 31 | return name; 32 | } 33 | public double getSalary() { 34 | return salary; 35 | } 36 | public LocalDate getHireDay() { 37 | return hireDay; 38 | } 39 | public void raiseSalary(double byPercent) { 40 | double raise = salary * byPercent / 100; 41 | salary += raise; 42 | } 43 | } -------------------------------------------------------------------------------- /src/第5章继承/5.7反射/CopyOfTest.java: -------------------------------------------------------------------------------- 1 | import java.lang.reflect.*; 2 | import java.util.*; 3 | 4 | public class CopyOfTest { 5 | public static void main(String[] args) { 6 | int[] a = {1, 2, 3}; 7 | a = (int[]) goodCopyOf(a, 10); 8 | System.out.println(Arrays.toString(a)); 9 | 10 | String[] b = {"Tom", "Dick", "Harry"}; 11 | b = (String[]) goodCopyOf(b, 10); 12 | System.out.println(Arrays.toString(b)); 13 | 14 | System.out.println("Will generate an Exception"); 15 | b = (String[]) badCopyOf(b, 10); 16 | } 17 | public static Object[] badCopyOf(Object[] a, int newLength) { 18 | Object[] newArray = new Object[newLength]; 19 | System.arraycopy(a, 0, newArray, 0, Math.min(a.length, newLength)); 20 | return newArray; 21 | } 22 | public static Object goodCopyOf(Object a, int newLength) { 23 | Class cl = a.getClass(); 24 | if(!cl.isArray()) return null; 25 | Class componentType = cl.getComponentType(); 26 | int length = Array.getLength(a); 27 | Object newArray = Array.newInstance(componentType, newLength); 28 | System.arraycopy(a, 0, newArray, 0, Math.min(length, newLength)); 29 | return newArray; 30 | } 31 | } -------------------------------------------------------------------------------- /src/第8章泛型程序设计/8.2定义简单的泛型类/PairTest.java: -------------------------------------------------------------------------------- 1 | public class PairTest { 2 | public static void main(String[] args) { 3 | String[] words = {"Mary", "had", "a", "little", "lamb"}; 4 | Pair mm = ArrayArg.minmax(words); 5 | System.out.println("min = " + mm.getFirst()); 6 | System.out.println("max = " + mm.getSecond()); 7 | } 8 | } 9 | class ArrayArg { 10 | public static Pair minmax(String[] a) { 11 | if(a == null || a.length == 0) return null; 12 | String min = a[0]; 13 | String max = a[1]; 14 | for(int i = 1; i < a.length; i++) { 15 | if(min.compareTo(a[i]) > 0) min = a[i]; 16 | if(max.compareTo(a[i]) < 0) max = a[i]; 17 | } 18 | return new Pair<>(min, max); 19 | } 20 | } 21 | class Pair { 22 | private T first; 23 | private T second; 24 | public Pair() { first = null; second = null; } 25 | public Pair(T first, T second) { 26 | this.first = first; 27 | this.second = second; 28 | } 29 | public T getFirst() { return first; } 30 | public T getSecond() { return second; } 31 | public void setFirst(T newValue) { first = newValue; } 32 | public void setSecond(T newValue) { second = newValue; } 33 | } -------------------------------------------------------------------------------- /src/第4章对象与类/4.6对象构造/ConstructorTest.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class ConstructorTest { 3 | public static void main(String[] args) { 4 | Employee[] staff = new Employee[3]; 5 | staff[0] = new Employee("Harry", 50000); 6 | staff[1] = new Employee(60000); 7 | staff[2] = new Employee(); 8 | 9 | for(Employee e : staff) 10 | e.print(); 11 | } 12 | } 13 | 14 | class Employee { 15 | private static int nextId; 16 | 17 | private int id; 18 | private String name = ""; 19 | private double salary; 20 | 21 | // static initialization block 22 | static { 23 | Random gen = new Random(); 24 | nextId = gen.nextInt(100000); 25 | } 26 | 27 | // object initialization block 28 | { 29 | id = nextId; 30 | nextId++; 31 | } 32 | 33 | Employee(String name, double salary) { 34 | this.name = name; 35 | this.salary = salary; 36 | } 37 | 38 | Employee(double salary) { 39 | this("Employee #" + nextId, salary); 40 | } 41 | 42 | Employee() {} 43 | 44 | public void print() { 45 | System.out.println("name = " + name + ", salary = " + salary 46 | + ", id = " + id); 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /src/第9章集合/9.3映射/MapUpdateAPI.java: -------------------------------------------------------------------------------- 1 | public class MapUpdateAPI { 2 | public static void main(String[] args) { 3 | // java.util.Map 4 | // default V merge(K key, V value, 5 | // BiFunction remappingFunction) 6 | // 如果 key 与非 null 值关联,将函数应用到 v 和 value,将 key 与结果关联 7 | // 如果结果为 null 则删除该键 8 | // 返回 get(key) 9 | 10 | // default V compute(K key, 11 | // BiFunction remappingFunction) 12 | // 将函数作用于 key 和 v 结果绑定到 key 13 | // 如果结果为 null 则删除该键 14 | // 返回 get(key) 15 | 16 | // default V computeIfPresent(K key, 17 | // BiFunction remappingFunction) 18 | // 如果 key 和一个非 null 值绑定,将函数作用于 key 和 v 结果绑定到 key 19 | // 如果结果为 null 则删除该键 20 | // 返回 get(key) 21 | 22 | // default V computeIfAbsent(K key, 23 | // Function mappingFunction) 24 | // 将函数应用到 key 除非 key 已经与非 null 值绑定,结果绑定到 key 25 | // 如果结果为 null 则删除该键 26 | // 返回 get(key) 27 | 28 | // default void replaceAll(BiFunction function) 29 | // 所有项上应用函数,将键与非 null 结果关联,null 结果删除对应项 30 | } 31 | } -------------------------------------------------------------------------------- /src/第4章对象与类/4.4静态域域静态方法/StaticTest.java: -------------------------------------------------------------------------------- 1 | import java.time.*; 2 | 3 | public class StaticTest 4 | { 5 | public static void main(String[] args) { 6 | Employee[] staff = new Employee[3]; 7 | 8 | staff[0] = new Employee("Tom", 40000); 9 | staff[1] = new Employee("Dick", 60000); 10 | staff[2] = new Employee("Harry", 65000); 11 | 12 | for(Employee e : staff) 13 | { 14 | e.setId(); 15 | System.out.println("name=" + e.getName() + ", id=" + e.getId() 16 | + ", salary=" + e.getSalary()); 17 | } 18 | System.out.println("nextId=" + Employee.getNextId()); 19 | 20 | } 21 | } 22 | 23 | class Employee { 24 | private static int nextId = 1; 25 | 26 | private String name; 27 | private double salary; 28 | private int id; 29 | 30 | public Employee(String n, double s) { 31 | name = n; 32 | salary = s; 33 | id = 0; 34 | } 35 | public String getName() { 36 | return name; 37 | } 38 | public double getSalary() { 39 | return salary; 40 | } 41 | public int getId() { 42 | return id; 43 | } 44 | public void setId() { 45 | id = nextId++; 46 | } 47 | public static int getNextId() { 48 | return nextId; 49 | } 50 | public static void main(String[] args) { 51 | Employee e = new Employee("Harry", 50000); 52 | System.out.println(e.getName() + " " + e.getSalary()); 53 | } 54 | } -------------------------------------------------------------------------------- /src/第7章异常断言和日志/7.2捕获异常/ExceptionAPI.java: -------------------------------------------------------------------------------- 1 | public class ExceptionAPI { 2 | public static void main(String[] args) { 3 | // java.lang.Throwable 4 | // Throwable(Throwable cause) 5 | // Throwable(String message, Throwable cause) 6 | 7 | // Throwable initCause(Throwable cause); 8 | // 设置原因,已经设置原因时会报异常 9 | // 返回 this 10 | 11 | // Throwable getCause() 12 | 13 | // StackTraceElement[] getStackTrace() 14 | 15 | // void addSuppressed(Throwable t) 16 | // Throwable[] getSuppressed() 17 | 18 | 19 | // java.lang.Exception 20 | // Exception(Throwable cause) 21 | // Exception(String message, Throwable cause) 22 | 23 | 24 | // java.lang.RuntimeException 25 | // RuntimeException(Throwable cause) 26 | // RuntimeException(String message, Throwable cause) 27 | 28 | 29 | // java.lang.StackTraceElement 30 | // String getFileName() 31 | // 源文件名 32 | 33 | // int getLineNumber() 34 | // 元素运行时对应的行号 35 | 36 | // String getClassName() 37 | // 对应类的完全限定名 38 | 39 | // String getMethodName() 40 | // 方法名,构造器对应 ,静态初始化器是 41 | // 无法区分同名的重载方法 42 | 43 | // boolean isNativeMethod() 44 | // 元素运行时在一个本地方法中返回 true 45 | 46 | // String toString() 47 | // 返回包含类名,方法名,文件名和行数的格式化字符串 48 | } 49 | } -------------------------------------------------------------------------------- /src/第5章继承/5.2Object所有类的超类/EqualsTest/Employee.java: -------------------------------------------------------------------------------- 1 | import java.time.*; 2 | import java.util.Objects; 3 | 4 | public class Employee { 5 | private String name; 6 | private double salary; 7 | private LocalDate hireDay; 8 | public Employee(String n, double s, int year, int month, int day) { 9 | name = n; 10 | salary = s; 11 | hireDay = LocalDate.of(year, month, day); 12 | } 13 | public String getName() { 14 | return name; 15 | } 16 | public double getSalary() { 17 | return salary; 18 | } 19 | public LocalDate getHireDay() { 20 | return hireDay; 21 | } 22 | public void raiseSalary(double byPercent) { 23 | double raise = salary * byPercent / 100; 24 | salary += raise; 25 | } 26 | 27 | @Override 28 | public boolean equals(Object otherObject) { 29 | if(this == otherObject) return true; 30 | if(otherObject == null) return false; 31 | if(getClass() != otherObject.getClass()) return false; 32 | Employee other = (Employee) otherObject; 33 | return Objects.equals(name, other.name) 34 | && salary == other.salary 35 | && Objects.equals(hireDay, other.hireDay); 36 | } 37 | 38 | public int hashCode() { 39 | return Objects.hash(name, salary, hireDay); 40 | } 41 | 42 | public String toString() { 43 | return getClass().getName() + "[name=" + name +",salary=" + salary 44 | + ",hireDay=" + hireDay + "]"; 45 | } 46 | } -------------------------------------------------------------------------------- /src/第6章接口lambda表达式与内部类/6.5代理/ProxyTest.java: -------------------------------------------------------------------------------- 1 | import java.lang.reflect.*; 2 | import java.util.*; 3 | 4 | public class ProxyTest { 5 | public static void main(String[] args) { 6 | Object[] elements = new Object[1000]; 7 | for(int i = 0; i < elements.length; i++) { 8 | Integer value = i + 1; 9 | InvocationHandler handler = new TraceHandler(value); 10 | Object proxy = Proxy.newProxyInstance(null, new Class[]{Comparable.class}, handler); 11 | elements[i] = proxy; 12 | } 13 | 14 | Integer key = new Random().nextInt(elements.length) + 1; 15 | int result = Arrays.binarySearch(elements, key); 16 | if(result >= 0) 17 | System.out.println(elements[result]); 18 | } 19 | } 20 | 21 | class TraceHandler implements InvocationHandler { 22 | private Object target; 23 | public TraceHandler(Object t) { 24 | target = t; 25 | } 26 | public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { 27 | System.out.print(target); 28 | System.out.print("." + m.getName() + "("); 29 | if(args != null) { 30 | for(int i = 0; i < args.length; i++) { 31 | System.out.print(args[i]); 32 | if(i < args.length - 1) System.out.print(", "); 33 | } 34 | } 35 | System.out.println(")"); 36 | return m.invoke(target, args); 37 | } 38 | } -------------------------------------------------------------------------------- /src/第9章集合/9.3映射/MapTest.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class MapTest { 4 | public static void main(String[] args) { 5 | Map staff = new HashMap<>(); 6 | staff.put("144-25-5464", new Employee("Amy Lee")); 7 | staff.put("567-24-2546", new Employee("Harry Hacker")); 8 | staff.put("157-62-7935", new Employee("Gary Cooper")); 9 | staff.put("456-62-5527", new Employee("Francesca Cruz")); 10 | System.out.println("org Map : \n" + staff); 11 | 12 | staff.remove("567-24-2546"); 13 | System.out.println("remove \"567-24-2546\" Map : \n" + staff); 14 | 15 | staff.put("456-62-5527", new Employee("Francesca Miller")); 16 | System.out.println("put (\"456-62-5527\", \"Francesca Miller\") Map : \n" + staff); 17 | 18 | System.out.println("get(\"157-62-7935\") : \n" + staff.get("157-62-7935")); 19 | 20 | System.out.println("getOrDefault(\"123-45-6789\", new Employee(\"Bob Smith\")) : \n" 21 | + staff.getOrDefault("123-45-6789", new Employee("Bob Smith"))); 22 | 23 | System.out.println("\nforEach : "); 24 | staff.forEach((k, v) -> System.out.println("key = " + k + ", value = " +v)); 25 | } 26 | } 27 | class Employee { 28 | private String name; 29 | Employee(String name) { 30 | this.name = name; 31 | } 32 | public String toString() { 33 | return "E[" + name + "]"; 34 | } 35 | } -------------------------------------------------------------------------------- /src/第8章泛型程序设计/8.4类型变量的限定/PairTest2.java: -------------------------------------------------------------------------------- 1 | import java.time.*; 2 | 3 | public class PairTest2 { 4 | public static void main(String[] args) { 5 | LocalDate[] birthdays = { 6 | LocalDate.of(1906, 12, 9), 7 | LocalDate.of(1815, 12, 10), 8 | LocalDate.of(1903, 12, 3), 9 | LocalDate.of(1910, 6, 22) 10 | }; 11 | Pair mm = ArrayArg.minmax(birthdays); 12 | System.out.println("min = " + mm.getFirst()); 13 | System.out.println("max = " + mm.getSecond()); 14 | } 15 | } 16 | class ArrayArg { 17 | public static Pair minmax(T[] a) { 18 | if(a == null || a.length == 0) return null; 19 | T min = a[0]; 20 | T max = a[1]; 21 | for(int i = 1; i < a.length; i++) { 22 | if(min.compareTo(a[i]) > 0) min = a[i]; 23 | if(max.compareTo(a[i]) < 0) max = a[i]; 24 | } 25 | return new Pair<>(min, max); 26 | } 27 | } 28 | class Pair { 29 | private T first; 30 | private T second; 31 | public Pair() { first = null; second = null; } 32 | public Pair(T first, T second) { 33 | this.first = first; 34 | this.second = second; 35 | } 36 | public T getFirst() { return first; } 37 | public T getSecond() { return second; } 38 | public void setFirst(T newValue) { first = newValue; } 39 | public void setSecond(T newValue) { second = newValue; } 40 | } -------------------------------------------------------------------------------- /src/第5章继承/5.2Object所有类的超类/EqualsTest/EqualsTest.java: -------------------------------------------------------------------------------- 1 | public class EqualsTest { 2 | public static void main(String[] args) { 3 | Employee alice1 = new Employee("Alice Adams", 75000, 1987, 12, 15); 4 | Employee alice2 = alice1; 5 | Employee alice3 = new Employee("Alice Adams", 75000, 1987, 12, 15); 6 | Employee bob = new Employee("Bob Brandson", 50000, 1989, 10, 1); 7 | 8 | System.out.println("alice1 == alice2 : " + (alice1 == alice2)); 9 | System.out.println("alice1 == alice3 : " + (alice1 == alice3)); 10 | System.out.println("alice1.equals(alice3) : " + (alice1.equals(alice3))); 11 | System.out.println("alice1.equals(bob) : " + (alice1.equals(bob))); 12 | 13 | System.out.println("\n========================\n"); 14 | 15 | Manager carl = new Manager("Carl Cracker", 80000, 1987, 12, 15); 16 | Manager boss = new Manager("Carl Cracker", 80000, 1987, 12, 15); 17 | boss.setBonus(5000); 18 | 19 | System.out.println("boss.toString() : " + boss); 20 | System.out.println("carl.equals(boss) : " + carl.equals(boss)); 21 | 22 | System.out.println("\n========================\n"); 23 | 24 | System.out.println("alice1.hashCode() : " + alice1.hashCode()); 25 | System.out.println("alice3.hashCode() : " + alice3.hashCode()); 26 | System.out.println("bob.hashCode() : " + bob.hashCode()); 27 | System.out.println("carl.hashCode() : " + carl.hashCode()); 28 | } 29 | } -------------------------------------------------------------------------------- /src/第2章Java程序设计环境/2.4运用图形化应用程序/ImageViewer.java: -------------------------------------------------------------------------------- 1 | import java.awt.*; 2 | import java.io.*; 3 | import javax.swing.*; 4 | 5 | public class ImageViewer { 6 | public static void main(String[] args) { 7 | EventQueue.invokeLater(() -> { 8 | JFrame frame = new ImageViewerFrame(); 9 | frame.setTitle("ImageViewer"); 10 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 11 | frame.setVisible(true); 12 | }); 13 | } 14 | } 15 | 16 | class ImageViewerFrame extends JFrame { 17 | private JLabel label; 18 | private JFileChooser chooser; 19 | private static final int DEFAULT_WIDTH = 300; 20 | private static final int DEFAULT_HEIGHT = 400; 21 | 22 | public ImageViewerFrame() { 23 | setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); 24 | label = new JLabel(); 25 | add(label); 26 | 27 | chooser = new JFileChooser(); 28 | chooser.setCurrentDirectory(new File(".")); 29 | 30 | JMenuBar menuBar = new JMenuBar(); 31 | setJMenuBar(menuBar); 32 | 33 | JMenu menu = new JMenu("File"); 34 | menuBar.add(menu); 35 | 36 | JMenuItem openItem = new JMenuItem("Open"); 37 | menu.add(openItem); 38 | 39 | openItem.addActionListener(event -> { 40 | int result = chooser.showOpenDialog(null); 41 | if(result == JFileChooser.APPROVE_OPTION) 42 | { 43 | String name = chooser.getSelectedFile().getPath(); 44 | label.setIcon(new ImageIcon(name)); 45 | } 46 | }); 47 | 48 | JMenuItem exitItem = new JMenuItem("Exit"); 49 | menu.add(exitItem); 50 | exitItem.addActionListener(event -> System.exit(0)); 51 | } 52 | } -------------------------------------------------------------------------------- /src/第8章泛型程序设计/8.9反射和泛型/GenericReflectionAPI.java: -------------------------------------------------------------------------------- 1 | public class GenericReflectionAPI { 2 | public static void main(String[] args) { 3 | // java.lang.Class 4 | // TypeVariable[] getTypeParameters() 5 | // 如果类型是泛型类型 获得泛型类型变量,否则返回0长数组 6 | 7 | // Type getGenericSuperclass() 8 | // 返回泛型的超类类型,如果是 Object 或不是一个类类型(class type) 则返回 null 9 | 10 | // Type[] getGenericInterfaces() 11 | // 返回这个类型的接口的泛型类型,如果没有实现接口返回 0 长数组 12 | 13 | // java.lang.reflect.Method 14 | // TypeVarible[] getTypeParameters() 15 | // 方法的泛型类型变量,非泛型方法返回 0 长数组 16 | 17 | // Type getGenericReturnType() 18 | // 获得返回类型 19 | 20 | // Type[] getGenericParameterTypes() 21 | // 方法被声明的泛型参数类型,没有参数则返回 0 长数组 22 | 23 | // java.lang.reflect.TypeVariable 24 | // String getName() 25 | // 获得类型变量的名字 26 | 27 | // Type[] getBounds() 28 | // 获得类型变量的子类限定,无限定则返回 0 长数组 29 | 30 | // java.lang.reflect.WildcardType 31 | // Type[] getUpperBounds() 32 | // 得到子类限定 33 | 34 | // Type[] getLowerBounds() 35 | // 得到超类限定 36 | 37 | // java.lang.reflect.ParameterizedType 38 | // Type getRawType() 39 | // 获得参数化类型的原始类型 40 | 41 | // Type[] getActualTypeArguments() 42 | // 获得参数化类型声明时所使用的类型参数 43 | 44 | // Type getOwnerType() 45 | // 如果是内部类型,则返回其外部类型,顶级类型返回 null 46 | 47 | // java.lang.reflect.GenericArrayType 48 | // Type getGenericComponentType() 49 | // 获得声明该数组乐行的泛型组件类型 50 | } 51 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.10数组/ArrayCopyTest.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class ArrayCopyTest { 3 | public static void main(String[] args) { 4 | int[] smallPrimes = {2,3,5,7,11,13}; 5 | 6 | System.out.println("Copy Reference"); 7 | 8 | int[] copyPrimes = smallPrimes; 9 | System.out.println("smallPrimes : " + Arrays.toString(smallPrimes)); 10 | System.out.println("copyPrimes : " + Arrays.toString(copyPrimes)); 11 | 12 | copyPrimes[1] = 23; 13 | System.out.println("copyPrimes[1] = 23;"); 14 | System.out.println("smallPrimes : " + Arrays.toString(smallPrimes)); 15 | System.out.println("copyPrimes : " + Arrays.toString(copyPrimes)); 16 | 17 | smallPrimes[3] = 17; 18 | System.out.println("smallPrimes[3] = 17;"); 19 | System.out.println("smallPrimes : " + Arrays.toString(smallPrimes)); 20 | System.out.println("copyPrimes : " + Arrays.toString(copyPrimes)); 21 | 22 | 23 | System.out.println("\nReal Copy"); 24 | 25 | int[] realCopy = Arrays.copyOf(smallPrimes, smallPrimes.length); 26 | System.out.println("smallPrimes : " + Arrays.toString(smallPrimes)); 27 | System.out.println("realCopy : " + Arrays.toString(realCopy)); 28 | 29 | smallPrimes[4] = 31; 30 | System.out.println("smallPrimes[4] = 31;"); 31 | System.out.println("smallPrimes : " + Arrays.toString(smallPrimes)); 32 | System.out.println("realCopy : " + Arrays.toString(realCopy)); 33 | 34 | realCopy[5] = 37; 35 | System.out.println("realCopy[5] = 37;"); 36 | System.out.println("smallPrimes : " + Arrays.toString(smallPrimes)); 37 | System.out.println("realCopy : " + Arrays.toString(realCopy)); 38 | } 39 | } -------------------------------------------------------------------------------- /src/第5章继承/5.2Object所有类的超类/EqualsTest.java: -------------------------------------------------------------------------------- 1 | import java.util.Objects; 2 | 3 | public class EqualsTest { 4 | public static void main(String[] args) { 5 | Employee e1 = new Employee("Alice", 50000); 6 | Employee m1 = new Manager("Alice", 50000, 30000); 7 | Employee e2 = new Employee("Alice", 50000); 8 | Employee m2 = new Manager("Alice", 50000, 20000); 9 | System.out.println("e1.equals(m1) = " + e1.equals(m1)); 10 | System.out.println("m1.equals(e1) = " + m1.equals(e1)); 11 | System.out.println("e1.equals(e2) = " + e1.equals(e2)); 12 | System.out.println("m1.equals(m2) = " + m1.equals(m2)); 13 | } 14 | } 15 | 16 | class Employee { 17 | private String name; 18 | private double salary; 19 | 20 | Employee(String name, double salary) { 21 | this.name = name; 22 | this.salary = salary; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | public double getSalary() { 29 | return salary; 30 | } 31 | 32 | @Override 33 | public boolean equals(Object otherObject) { 34 | if(this == otherObject) return true; 35 | if(otherObject == null) return false; 36 | if(getClass() != otherObject.getClass()) return false; 37 | Employee other = (Employee) otherObject; 38 | return Objects.equals(name, other.getName()) 39 | && salary == other.getSalary(); 40 | } 41 | } 42 | 43 | class Manager extends Employee { 44 | private double bonus; 45 | Manager(String name, double salary, double bonus) { 46 | super(name, salary); 47 | this.bonus = bonus; 48 | } 49 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.6字符串/StringAPI.java: -------------------------------------------------------------------------------- 1 | public class StringAPI { 2 | public static void main(String[] args) { 3 | // char charAt(int index) 返回某个位置的代码单元 4 | 5 | // int codePointAt(int index) 返回某个位置开始的码点 6 | 7 | // int offsetByCodePoints(int startIndex, int cpCount) 8 | // startIndex 开始,位移 cpCount 单位后的码点索引 9 | 10 | // int compareTo(String other) 字典序比较结果 11 | // other 小则返回正数,相等返回0,否则返回负数 12 | 13 | // IntStream codePoints() 返回码点的流,配合toArray方法生成数组 14 | 15 | // new String(int[] codePoints, int offset, int count) 16 | // 从数组 offset 开始 count 个码点生成串 17 | 18 | // boolean equals(Object other) 字符串与other相等返回true 19 | 20 | // boolean equalsIgnoreCase(String other) 忽略大小写比较 21 | 22 | // boolean startsWith(String prefix) 以 prefix 开始 23 | 24 | // boolean endsWith(String suffix) 以 suffix 结束 25 | 26 | // int indexOf(String str) 27 | // int indexOf(String str, int fromIndex) 28 | // int indexOf(int cp) 29 | // int indexOf(int cp,int fromIndex) 30 | // 返回与串 str 或码点 cp 匹配的最后一个子串开始位置 31 | 32 | // int length() 返回长度 33 | 34 | // int codePointCount(int startIndex, int endIndex) 35 | // 返回 [startIndex, endIndex) 之间的码点数量, 36 | // 没有配成对的替代字符计入码点数 37 | 38 | // String replace(CharSequence oldString, CharSequence newString) 39 | // 返回一个新的字符串,新字符串将旧的所有 oldString 替换为 newString 40 | // CharSequence 可以是 String 或者 StringBuilder 41 | 42 | // String substring(int beginIndex) 43 | // String substring(int beginIndex, int endIndex) 44 | 45 | // String toLowerCase() 46 | // String toUpperCase() 47 | 48 | // String trim() 返回去掉首尾空格的新串 49 | 50 | // String join(CharSequence delimiter, CharSequence... elements) 51 | // 返回用给定的定界符连接所有的元素 52 | } 53 | } -------------------------------------------------------------------------------- /src/第5章继承/5.3泛型数组列表/arrayList/ArrayListTest.java: -------------------------------------------------------------------------------- 1 | import java.time.*; 2 | import java.util.*; 3 | 4 | public class ArrayListTest { 5 | public static void main(String[] args) { 6 | ArrayList staff = new ArrayList<>(); 7 | 8 | staff.add(new Employee("Carl Cracker", 75000, 1987, 12, 15)); 9 | staff.add(new Employee("Harry Hacker", 50000, 1989, 10, 1)); 10 | //staff.set(2, new Employee("Tony Tester", 40000, 1990, 3, 15)); 11 | // java.lang.IndexOutOfBoundsException 12 | staff.add(new Employee("Tony Tester", 40000, 1990, 3, 15)); 13 | 14 | for(Employee e : staff) 15 | e.raiseSalary(5); 16 | 17 | for(Employee e : staff) 18 | System.out.println("name=" + e.getName() + ", salary=" + e.getSalary() 19 | + ", hireDay=" + e.getHireDay()); 20 | 21 | System.out.println("\n===============\n"); 22 | 23 | System.out.println(staff.get(0)); 24 | 25 | staff.remove(0); 26 | System.out.println(staff.get(0)); 27 | 28 | } 29 | } 30 | 31 | class Employee { 32 | private String name; 33 | private double salary; 34 | private LocalDate hireDay; 35 | public Employee(String n, double s, int year, int month, int day) { 36 | name = n; 37 | salary = s; 38 | hireDay = LocalDate.of(year, month, day); 39 | } 40 | public String getName() { 41 | return name; 42 | } 43 | public double getSalary() { 44 | return salary; 45 | } 46 | public LocalDate getHireDay() { 47 | return hireDay; 48 | } 49 | public void raiseSalary(double byPercent) { 50 | double raise = salary * byPercent / 100; 51 | salary += raise; 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | return "name = " + name + ", salary = " + salary 57 | + ", hireDay = " + hireDay; 58 | } 59 | } -------------------------------------------------------------------------------- /src/第9章集合/9.3映射/SpecialSetMapAPI.java: -------------------------------------------------------------------------------- 1 | public class SpecialSetMapAPI { 2 | public static void main(String[] args) { 3 | // java.util.WeakHashMap 4 | // WeakHashMap() 5 | // WeakHashMap(int initialCapacity) 6 | // WeakHashMap(int initialCapacity, float loadFactor) 7 | 8 | 9 | // java.util.LinkedHashSet 10 | // LinkedHashSet() 11 | // LinkedHashSet(int initialCapacity) 12 | // linkedHashSet(int initialCapacity, float loadFactor) 13 | 14 | 15 | // java.util.LinkedHashMap 16 | // LinkedHashMap() 17 | // LinkedHashMap(int initialCapacity) 18 | 19 | // LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) 20 | // accessOrder true 表示访问顺序,false 表示插入顺序 21 | 22 | // prodtected boolean removeEldestEntry(Map.Entry eldest) 23 | // eldest 是预期要删除的参数 24 | // 默认是总返回 false 25 | 26 | 27 | // java.util.EnumSet> 28 | // static > EnumSet allOf(Class enumType) 29 | // static > EnumSet noneOf(Class enumType) 30 | // static > EnumSet range(E from, E to) 31 | // static > EnumSet of(E value) 32 | // static > EnumSet of(E value, E... values) 33 | 34 | 35 | // java.util.EnumMap> 36 | // EnumMap(Class keyType) 37 | 38 | 39 | // java.util.IdentityHashMap 40 | // IdentityHashMap() 41 | // IdentityHashMap(int expectedMaxSize) 42 | 43 | 44 | // java.lang.System 45 | // static int identityHashCode(Object obj) 46 | } 47 | } -------------------------------------------------------------------------------- /src/第5章继承/5.2Object所有类的超类/EqualsTest3.java: -------------------------------------------------------------------------------- 1 | import java.util.Objects; 2 | 3 | public class EqualsTest3 { 4 | public static void main(String[] args) { 5 | Employee e1 = new Employee("Alice", 50000); 6 | Employee m1 = new Manager("Alice", 50000, 30000); 7 | Employee e2 = new Employee("Alice", 50000); 8 | Employee m2 = new Manager("Alice", 50000, 20000); 9 | System.out.println("e1.equals(m1) = " + e1.equals(m1)); 10 | System.out.println("m1.equals(e1) = " + m1.equals(e1)); 11 | System.out.println("e1.equals(e2) = " + e1.equals(e2)); 12 | System.out.println("m1.equals(m2) = " + m1.equals(m2)); 13 | } 14 | } 15 | 16 | class Employee { 17 | private String name; 18 | private double salary; 19 | 20 | Employee(String name, double salary) { 21 | this.name = name; 22 | this.salary = salary; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | public double getSalary() { 29 | return salary; 30 | } 31 | 32 | @Override 33 | public boolean equals(Object otherObject) { 34 | if(this == otherObject) return true; 35 | if(otherObject == null) return false; 36 | if(!(otherObject instanceof Employee)) return false; 37 | Employee other = (Employee) otherObject; 38 | return Objects.equals(name, other.getName()) 39 | && salary == other.getSalary(); 40 | } 41 | } 42 | 43 | class Manager extends Employee { 44 | private double bonus; 45 | Manager(String name, double salary, double bonus) { 46 | super(name, salary); 47 | this.bonus = bonus; 48 | } 49 | public double getBonus() { 50 | return bonus; 51 | } 52 | } -------------------------------------------------------------------------------- /src/第9章集合/9.2具体的集合/TreeSetTest.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class TreeSetTest { 4 | public static void main(String[] args) { 5 | SortedSet parts = new TreeSet(); 6 | parts.add(new Item("Toaster", 1234)); 7 | parts.add(new Item("Widget", 4562)); 8 | parts.add(new Item("Modem", 9912)); 9 | System.out.println(parts); 10 | 11 | NavigableSet sortByDescription = new TreeSet<>( 12 | Comparator.comparing(Item::getDescription) 13 | ); 14 | sortByDescription.addAll(parts); 15 | System.out.println(sortByDescription); 16 | } 17 | } 18 | 19 | class Item implements Comparable { 20 | private String description; 21 | private int partNumber; 22 | 23 | public Item(String description, int partNumber) { 24 | this.description = description; 25 | this.partNumber = partNumber; 26 | } 27 | public String getDescription() { 28 | return description; 29 | } 30 | public int getPartNumber() { 31 | return partNumber; 32 | } 33 | public String toString() { 34 | return "[description = " + description + ", partNumber = " + partNumber + "]"; 35 | } 36 | public boolean equals(Object otherObject) { 37 | if(this == otherObject) return true; 38 | if(otherObject == null) return false; 39 | if(getClass() != otherObject.getClass()) return false; 40 | Item other = (Item) otherObject; 41 | return Objects.equals(description, other.description) && partNumber == other.partNumber; 42 | } 43 | public int hashCode() { 44 | return Objects.hash(description, partNumber); 45 | } 46 | public int compareTo(Item other) { 47 | int diff = Integer.compare(partNumber, other.partNumber); 48 | return diff != 0 ? diff : description.compareTo(other.description); 49 | } 50 | } -------------------------------------------------------------------------------- /src/第9章集合/9.5算法/SimpleAlgorithmAPI.java: -------------------------------------------------------------------------------- 1 | public class SimpleAlgorithmAPI { 2 | public static void main(String[] args) { 3 | // java.util.Collections 4 | // static > T min(Collection elements) 5 | // static > T max(Collection elements) 6 | // static T min(Collection elements, Comparator c) 7 | // static T max(Collection elements, Comparator c) 8 | // 返回集合最小,最大的元素 9 | 10 | // static void copy(List to, List from) 11 | // 复制,目标位置长度至少和原列表一样 12 | 13 | // static void fill(List list, T value) 14 | // list 所有元素都用 value 填充 15 | 16 | // static boolean addAll(Collection c, T... values) 17 | // 所有 values 添加到 c 如果 c 改变了返回 true 18 | 19 | // static boolean replaceAll(List list, T oldValue, T newValue) 20 | 21 | // static int indexOfSubList(List list, List s) 22 | // static int lastIndexOfSubList(List list, List s) 23 | // 返回第一个或者最后一个等于子列表的索引 24 | // 没有则返回 -1 25 | 26 | // static void swap(List list, int i, int j) 27 | // 交换元素 28 | 29 | // static void reverse(List list) 30 | 31 | // static void rotate(List list, int d) 32 | // 将 i 条目移动到 (i + d) % list.size() 的位置 33 | 34 | // static int frequency(Collection c, Object o) 35 | // c 中与 o 数量相同的元素个数 36 | 37 | // boolean disjoint(Collection c1, Collection c2) 38 | // 两个集合没有公共元素 返回 true 39 | 40 | 41 | // java.util.Collection 42 | // default boolean removeIf(Predicate filter) 43 | // 删除所有 filter 返回 true 的元素 44 | 45 | // default void replaceAll(UnaryOperator op) 46 | // 列表中所有元素应用 op 操作 47 | } 48 | } -------------------------------------------------------------------------------- /src/第3章Java的基本程序设计结构/3.10数组/ArraysAPI.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class ArraysAPI { 3 | public static void main(String[] args) { 4 | int[] arr = new int[10]; 5 | for(int i = 0; i < 10; i++) 6 | arr[i] = i; 7 | A[] arrObj = new A[10]; 8 | for(int i = 0; i < 10; i++) 9 | arrObj[i] = new A(i, 9 - i); 10 | 11 | // static String toString(type[] a) 12 | System.out.println("arr : " + Arrays.toString(arr)); 13 | System.out.println("arrObj : " + Arrays.toString(arrObj)); 14 | 15 | // static type copyOf(type[] a,int length) 16 | int[] arrB = Arrays.copyOf(arr, arr.length - 5); 17 | print("copyOf(arr, arr.length - 5)", arrB); 18 | int[] arrC = Arrays.copyOf(arr, arr.length + 5); 19 | System.out.println("copyOf(arr, arr.length + 5) : " + Arrays.toString(arrC)); 20 | 21 | A[] objArrB = Arrays.copyOf(arrObj, arrObj.length - 5); 22 | System.out.println("copyOf(arrObj, arrObj.length - 5) : " + Arrays.toString(arrObj)); 23 | 24 | 25 | // static type copyOfRange(type[] a, int start, int end) 26 | // 复制 [start, end) 可能 end 会大于 a.length 27 | 28 | // static void sort(type[] a) 29 | 30 | // static int binarySearch(type[] a, type v) 31 | // static int binarySearch(type[] a, int start, int end, type v) 32 | 33 | // static void fill(type[] a, type v) 34 | // 将 a 中所有元素填成 v 35 | 36 | // static boolean equals(type[] a, type[] b) 37 | // 数组大小相同且元素相同则返回 true 38 | } 39 | static void print(String s, int[] arr) { 40 | System.out.print(s + " : "); 41 | System.out.println(Arrays.toString(arr)); 42 | } 43 | static void print(String s, Object[] arr) { 44 | System.out.print(s + " : "); 45 | System.out.println(Arrays.toString(arr)); 46 | } 47 | } 48 | class A { 49 | public int a; 50 | public int b; 51 | A(int a, int b) { 52 | this.a = a; 53 | this.b = b; 54 | } 55 | @Override 56 | public String toString() { 57 | return "(a, b) = (" + a + ", " + b + ")"; 58 | } 59 | } -------------------------------------------------------------------------------- /src/第5章继承/5.2Object所有类的超类/EqualsTest2.java: -------------------------------------------------------------------------------- 1 | import java.util.Objects; 2 | 3 | public class EqualsTest2 { 4 | public static void main(String[] args) { 5 | Employee e1 = new Employee("Alice", 50000); 6 | Employee m1 = new Manager("Alice", 50000, 30000); 7 | Employee e2 = new Employee("Alice", 50000); 8 | Employee m2 = new Manager("Alice", 50000, 20000); 9 | System.out.println("e1.equals(m1) = " + e1.equals(m1)); 10 | System.out.println("m1.equals(e1) = " + m1.equals(e1)); 11 | System.out.println("e1.equals(e2) = " + e1.equals(e2)); 12 | System.out.println("m1.equals(m2) = " + m1.equals(m2)); 13 | } 14 | } 15 | 16 | class Employee { 17 | private String name; 18 | private double salary; 19 | 20 | Employee(String name, double salary) { 21 | this.name = name; 22 | this.salary = salary; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | public double getSalary() { 29 | return salary; 30 | } 31 | 32 | @Override 33 | public boolean equals(Object otherObject) { 34 | if(this == otherObject) return true; 35 | if(otherObject == null) return false; 36 | if(getClass() != otherObject.getClass()) return false; 37 | Employee other = (Employee) otherObject; 38 | return Objects.equals(name, other.getName()) 39 | && salary == other.getSalary(); 40 | } 41 | } 42 | 43 | class Manager extends Employee { 44 | private double bonus; 45 | Manager(String name, double salary, double bonus) { 46 | super(name, salary); 47 | this.bonus = bonus; 48 | } 49 | public double getBonus() { 50 | return bonus; 51 | } 52 | @Override 53 | public boolean equals(Object otherObject) { 54 | if(!super.equals(otherObject)) return false; 55 | Manager other = (Manager)otherObject; 56 | return bonus == other.getBonus(); 57 | } 58 | } -------------------------------------------------------------------------------- /src/第6章接口lambda表达式与内部类/6.2接口示例/cloneTest/CloneTest.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class CloneTest { 4 | public static void main(String[] args) { 5 | try { 6 | Employee original = new Employee("John Q.", 50000); 7 | original.setHireDay(2000, 1, 1); 8 | Employee copy = original.clone(); 9 | copy.raiseSalary(10); 10 | copy.setHireDay(2002, 12, 31); 11 | System.out.println("original = " + original); 12 | System.out.println("copy = " + copy); 13 | 14 | System.out.println("\n================\n"); 15 | Employee[] staff = new Employee[3]; 16 | staff[0] = new Employee("Alice", 10000); 17 | staff[1] = new Employee("Bob", 20000); 18 | staff[2] = new Employee("Chris", 30000); 19 | Employee[] copyStaff = staff.clone(); 20 | 21 | System.out.println("staff before operation"); 22 | for(Employee e : staff) 23 | System.out.println(e); 24 | 25 | copyStaff[0].setHireDay(1995,1,1); 26 | copyStaff[1].setHireDay(1996,1,1); 27 | copyStaff[2].setHireDay(1997,1,1); 28 | 29 | System.out.println("staff"); 30 | for(Employee e : staff) 31 | System.out.println(e); 32 | System.out.println("copyStaff"); 33 | for(Employee e : copyStaff) 34 | System.out.println(e); 35 | 36 | System.out.println("\n================\n"); 37 | Manager m = new Manager("Harry" , 50000, 50000); 38 | System.out.println("Original Manager " + m); 39 | System.out.println("m instanceof Cloneable : " + (m instanceof Cloneable)); 40 | Manager copyM = (Manager) m.clone(); 41 | copyM.setChargeDay(2020,1,1); 42 | System.out.println("Manager " + m); 43 | System.out.println("Copy Manager " + copyM); 44 | 45 | } catch (CloneNotSupportedException e) { 46 | e.printStackTrace(); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /src/第4章对象与类/4.5方法参数/ParamTest.java: -------------------------------------------------------------------------------- 1 | public class ParamTest { 2 | public static void main(String[] args) { 3 | // Methods can not modify numeric parameters 4 | System.out.println("Testing numeric parameter"); 5 | double percent = 10; 6 | System.out.println("Before: percent = " + percent); 7 | tripleValue(percent); 8 | System.out.println("After: percent = " + percent); 9 | 10 | // Methods can change the state of object parameters 11 | System.out.println("\nTesting state of object parameters"); 12 | Employee harry = new Employee("Harry", 50000); 13 | System.out.println("Before: salary = " + harry.getSalary()); 14 | tripleSalary(harry); 15 | System.out.println("After: salary = " + harry.getSalary()); 16 | 17 | // Methods can not attach new objects to object parameters 18 | System.out.println("\nTesting object parameters"); 19 | Employee a = new Employee("Alice", 70000); 20 | Employee b = new Employee("Bob", 60000); 21 | System.out.println("Before: a = " + a.getName()); 22 | System.out.println("Before: b = " + b.getName()); 23 | swap(a, b); 24 | System.out.println("After: a = " + a.getName()); 25 | System.out.println("After: b = " + b.getName()); 26 | } 27 | 28 | public static void tripleValue(double x) { 29 | x *= 3; 30 | System.out.println("End of method: x = " + x); 31 | } 32 | public static void tripleSalary(Employee e) { 33 | e.raiseSalary(200); 34 | System.out.println("End of method: salary = " + e.getSalary()); 35 | } 36 | 37 | public static void swap(Employee x, Employee y) { 38 | Employee tmp = x; 39 | x = y; 40 | y = tmp; 41 | System.out.println("End of method: E x = " + x.getName()); 42 | System.out.println("End of method: E y = " + y.getName()); 43 | } 44 | } 45 | class Employee { 46 | private String name; 47 | private double salary; 48 | 49 | public Employee(String n, double s) { 50 | name = n; 51 | salary = s; 52 | } 53 | public String getName() { 54 | return name; 55 | } 56 | public double getSalary() { 57 | return salary; 58 | } 59 | public void raiseSalary(double byPercent) { 60 | double raise = salary * byPercent / 100; 61 | salary += raise; 62 | } 63 | } -------------------------------------------------------------------------------- /notes/Java核心技术卷一1.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 《Java核心技术卷一》 笔记 1 4 | 5 | 2019.06.06 17:18 6 | 7 | 8 | 9 | ## 第1章 Java程序设计概述 10 | 11 | ### 1.1 Java程序设计平台 12 | 13 | Java 不仅仅是一种语言,同时也是一个程序设计平台和一个庞大的库,提供了很多可重用的代码和一个提供安全性、可移植性、自动垃圾回收的执行环境。 14 | 15 | ### 1.2 Java “白皮书”的关键术语 16 | 17 | 简单性:Java简化了很多C++的语法。有一个适合嵌入式的Java Micro Edition 18 | 19 | 面向对象:将重心放在数据对象和对象的接口上的程序设计技术。 20 | 21 | ​ Java没有多重继承机制而使用接口 22 | 23 | 分布式:Java有处理HTTP、FTP之类协议的类库可以方便的通过URL访问网络上的对象 24 | 25 | 健壮性:Java编译时检查比很多语言更细致, 26 | 27 | ​ Java的指针模型可以消除重写内存和损坏数据的可能 28 | 29 | 安全性:Java程序运行在沙箱中因此不会影响主系统。Java拥有复杂的安全模型。 30 | 31 | 体系结构中立:Java编译产生与机器无关的字节码,再通过虚拟机运行。 32 | 33 | ​ 可以通过即时编译的手段把执行最频繁的代码编译称为机器码 34 | 35 | 可移植性:Java 规范没有依赖具体实现的地方,基本类型大小及相关运算都是明确的 36 | 37 | ​ 除了UI以外的库都有很好的支持平台独立性 38 | 39 | 解释型:Java解释器可以在任何移植了解释器的机器上执行字节码。 40 | 41 | ​ 链接是一个增量式且轻量级的过程,所以开发是快捷且具有探索性的 42 | 43 | 高性能:即时编译技术 44 | 45 | 多线程:支持在多核处理器上的并发程序设计 46 | 47 | 动态性:Java库中可以自有添加新方法和变量而不影响客户端。 48 | 49 | ​ Java中找出运行时类型信息十分容易 50 | 51 | 52 | 53 | ### 1.3 Java applet 与 Internet 54 | 55 | 用户从 Internet 下载字节码在自己机器上运行。在网页中运行的Java程序称为applet。 56 | 57 | 使用applet需要启用Java的Web浏览器执行字节码, 58 | 59 | 任何时候访问包含applet的网页都会得到程序的最新版本 60 | 61 | 虚拟机的安全性保证不会受到恶意代码的攻击 62 | 63 | applet就像一个可以和用户交互的图片 64 | 65 | 但现在applet缤购试试很流行 66 | 67 | 68 | 69 | ### 1.4 Java发展简史 70 | 71 | 1991 Patrick Naughton 和 James Gosling 带领 Sun 公司的小组设计了不与体系结构绑定的计算机语言 项目名为 Green。 Gosling 命名语言为 Oak 但是 Oak 已经是计算机语言了 于是起名Java 72 | 73 | 1992 Green 发布了第一个产品 “*7” 智能远程控制 74 | 75 | 1994-1995 Java 写的 HotJava 浏览器诞生 76 | 77 | 1996 Java 1.0 发布 78 | 79 | 1998 Java 1.2 Java 成为服务器端的首选 80 | 81 | 2004 Java 5.0 发布 foreach语法 82 | 83 | 2009 Oracle 收购 Sun 84 | 85 | 2011 Java 7 发布 字符串switch 钻石操作符 异常处理改进 86 | 87 | 2014 Java 8 发布 函数式编程 lambda表达式 流和日期时间库 88 | 89 | 90 | 91 | ### 1.5 关于 Java 的常见误解 92 | 93 | 以下是正确的说法: 94 | 95 | Java 不是 HTML 的扩展 96 | 97 | 使用 XML 和使用 Java 没有关系 98 | 99 | Java 功能强大学习成本也很高 100 | 101 | Java 并不能适用于所有平台,比如 JavaScript 开发浏览器端,Obj-C 和 Swift 开发 iOS,C++、C# 开发 Windows 应用。Java 主要用于服务端和跨平台客户端应用。 102 | 103 | Java 除了作为一个编程语言,同时提供了一套成熟的软件生态 104 | 105 | Java 逐渐开源了(2007年起GPL许可) 106 | 107 | 除了applet以外的大多数Java程序都是在Web浏览器以外独立运行的 108 | 109 | 同其他执行平台比较,Java是很安全的 110 | 111 | JavaScript 与 Java 没多大关系 112 | 113 | Internet 设备还不能取代桌面计算机。但现在的终端在向手机和平板电脑转化,其操作系统是Android。Java 对 Android 开发有帮助。 114 | 115 | -------------------------------------------------------------------------------- /src/第5章继承/5.7反射/objectAnalyzer/ObjectAnalyzer.java: -------------------------------------------------------------------------------- 1 | import java.lang.reflect.*; 2 | import java.util.ArrayList; 3 | 4 | public class ObjectAnalyzer { 5 | private ArrayList visited = new ArrayList<>(); 6 | public String toString(Object obj) { 7 | return toString(obj, 4); 8 | } 9 | String getIndent(int indent) { 10 | StringBuilder sb = new StringBuilder(); 11 | for(int i = 0; i < indent; i++) 12 | sb.append(' '); 13 | return sb.toString(); 14 | } 15 | public String toString(Object obj, int indent) { 16 | if(obj == null) return "null"; 17 | if(visited.contains(obj)) return "..."; 18 | visited.add(obj); 19 | Class cl = obj.getClass(); 20 | if(cl == String.class) return (String) obj; 21 | // array 22 | if(cl.isArray()) { 23 | String r = cl.getComponentType() + "[]{"; 24 | for(int i = 0; i < Array.getLength(obj); i++) { 25 | if(i > 0) r += ","; 26 | r += "\n" + getIndent(indent); 27 | Object val = Array.get(obj, i); 28 | if(cl.getComponentType().isPrimitive()) r += val; 29 | else r += toString(val, indent + 4); 30 | } 31 | return r + "\n" + getIndent(indent - 4) + "}"; 32 | } 33 | // field of this and super class 34 | String r = cl.getName(); 35 | do { 36 | r += "["; 37 | Field[] fields = cl.getDeclaredFields(); 38 | AccessibleObject.setAccessible(fields, true); 39 | for(Field f : fields) { 40 | if(!Modifier.isStatic(f.getModifiers())) { 41 | if(!r.endsWith("[")) r += ","; 42 | r += "\n" + getIndent(indent) + f.getName() + "="; 43 | try { 44 | Class t = f.getType(); 45 | Object val = f.get(obj); 46 | if(t.isPrimitive()) r += val; 47 | else r += toString(val, indent + 4); 48 | } catch (Exception e) { 49 | e.printStackTrace(); 50 | } 51 | } 52 | } 53 | if(!r.endsWith("[")) 54 | r += "\n" + getIndent(indent - 4); 55 | r += "]"; 56 | cl = cl.getSuperclass(); 57 | }while(cl != null); 58 | return r; 59 | } 60 | } -------------------------------------------------------------------------------- /src/第6章接口lambda表达式与内部类/6.3lambda表达式/ComparatorTest.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class ComparatorTest { 4 | public static void main(String[] args) { 5 | Person[] people = new Person[6]; 6 | people[0] = new Person("bbc", "bwec", "sdg"); 7 | people[1] = new Person("bawe", "bwqec", "absgd"); 8 | people[2] = new Person("sdb", null, "cxzagagd"); 9 | people[3] = new Person("dg", "ec", "sggad"); 10 | people[4] = new Person("asgag", "abqwec", "sdg"); 11 | people[5] = new Person("gdg", null, "sgd"); 12 | show("original array :", people); 13 | 14 | Arrays.sort(people, Comparator.comparing(Person::getLastName)); 15 | show("Sorted by last name :", people); 16 | 17 | Arrays.sort(people, 18 | Comparator.comparing(Person::getLastName) 19 | .thenComparing(Person::getFirstName)); 20 | show("Sorted by last name (then first name) :", people); 21 | 22 | Arrays.sort(people, 23 | Comparator.comparing(Person::getLastName, 24 | (s, t) -> Integer.compare(s.length(), t.length()))); 25 | show("Sorted by last name length :", people); 26 | 27 | Arrays.sort(people, Comparator.comparingInt(p -> p.getLastName().length())); 28 | show("Sorted by last name length :", people); 29 | 30 | Arrays.sort(people, Comparator.comparing(Person::getMiddleName, 31 | Comparator.nullsFirst(Comparator.naturalOrder()))); 32 | show("Sorted by middle name (null first) :", people); 33 | } 34 | public static void show(String s, Person[] arr) { 35 | System.out.print(s); 36 | boolean fi = true; 37 | for(Person p : arr) { 38 | if(!fi) System.out.print(","); 39 | fi = false; 40 | System.out.println(); 41 | System.out.print(" " + p.getFirstName() + " " 42 | + p.getMiddleName() + " " + p.getLastName()); 43 | } 44 | System.out.println('\n'); 45 | } 46 | } 47 | class Person { 48 | private String firstName, middleName, lastName; 49 | Person(String fi, String mi, String la) { 50 | firstName = fi; 51 | middleName = mi; 52 | lastName = la; 53 | } 54 | String getFirstName() { 55 | return firstName; 56 | } 57 | String getMiddleName() { 58 | return middleName; 59 | } 60 | String getLastName() { 61 | return lastName; 62 | } 63 | } -------------------------------------------------------------------------------- /src/第4章对象与类/4.6对象构造/ConstructOrderTest.java: -------------------------------------------------------------------------------- 1 | public class ConstructOrderTest { 2 | static { 3 | System.out.println("Add ConstructOrderTest class"); 4 | } 5 | public static void main(String[] args) { 6 | System.out.println("Begin Main\n"); 7 | ClassA objA = new ClassA(); 8 | System.out.println("====================\nshow objA"); 9 | objA.print(); 10 | System.out.println("\n ======================== \n"); 11 | ClassA objB = new ClassA(5); 12 | System.out.println("====================\nshow objB"); 13 | objB.print(); 14 | System.out.println("\nEnd Main"); 15 | } 16 | } 17 | 18 | class ClassA { 19 | static public void main(String[] args) { 20 | System.out.println("Begin ClassA Main"); 21 | System.out.println("End ClassA Main"); 22 | } 23 | 24 | ClassA() { 25 | System.out.println("Begin ClassA()"); 26 | System.out.println("End ClassA()"); 27 | } 28 | ClassA(int a) { 29 | this(); 30 | System.out.println("Begin ClassA(int)"); 31 | print(); 32 | this.a = a; 33 | print(); 34 | System.out.println("End ClassA(int)"); 35 | } 36 | 37 | static int sa = -1; 38 | 39 | int a = -1; 40 | int b = -1; 41 | 42 | { 43 | System.out.println("Begin: Object Initialization Block 1"); 44 | print(); 45 | a = 1; 46 | c = 1; 47 | print(); 48 | System.out.println("End: Object Initialization Block 1\n"); 49 | } 50 | 51 | public void print() { 52 | System.out.println("a = " + a + ", b = " + b + ", c = " + c); 53 | } 54 | 55 | private int c = -1; 56 | 57 | { 58 | System.out.println("Begin: Object Initialization Block 2"); 59 | print(); 60 | b = 2; 61 | c = 2; 62 | print(); 63 | System.out.println("End: Object Initialization Block 2\n"); 64 | } 65 | 66 | static { 67 | System.out.println("Begin: Static Initialization Block 1"); 68 | sprint(); 69 | sa = 1; 70 | sc = 1; 71 | sprint(); 72 | System.out.println("End: Static Initialization Block 1\n"); 73 | } 74 | 75 | public static void sprint() { 76 | System.out.println("sa = " + sa + ", sb = " + sb + ", sc = " + sc); 77 | } 78 | 79 | static int sb = -1; 80 | static int sc = -1; 81 | 82 | static { 83 | System.out.println("Begin: Static Initialization Block 2"); 84 | sprint(); 85 | sb = 2; 86 | sc = 2; 87 | sprint(); 88 | System.out.println("End: Static Initialization Block 2\n"); 89 | } 90 | 91 | } -------------------------------------------------------------------------------- /src/第8章泛型程序设计/8.5泛型代码和虚拟机/BridgeMethodTest.java: -------------------------------------------------------------------------------- 1 | import java.time.*; 2 | 3 | public class BridgeMethodTest { 4 | public static void main(String[] args) { 5 | Pair di = new Pair(LocalDate.of(1995,5,1),LocalDate.of(2000,5,1)); 6 | System.out.println("di : " + di); 7 | di.setSecond(LocalDate.of(1900,5,1)); 8 | System.out.println("di.setSecond(LocalDate.of(1900,5,1)) : " + di); 9 | di.setSecond(LocalDate.of(2010,5,1)); 10 | System.out.println("di.setSecond(LocalDate.of(2010,5,1)) : " + di); 11 | 12 | System.out.println("\n===========================\n"); 13 | 14 | DateInterval di2 = new DateInterval(LocalDate.of(1995,5,1),LocalDate.of(2000,5,1)); 15 | System.out.println("di2 : " + di2); 16 | di2.setSecond(LocalDate.of(1900,5,1)); 17 | System.out.println("di2.setSecond(LocalDate.of(1900,5,1)) : " + di2); 18 | di2.setSecond(LocalDate.of(2010,5,1)); 19 | System.out.println("di2.setSecond(LocalDate.of(2010,5,1)) : " + di2); 20 | 21 | System.out.println("\n===========================\n"); 22 | LocalDate ld = di2.getSecond(); 23 | System.out.println("ld : " + ld); 24 | } 25 | } 26 | class Pair { 27 | private T first; 28 | private T second; 29 | public Pair() { first = null; second = null; } 30 | public Pair(T first, T second) { 31 | this.first = first; 32 | this.second = second; 33 | } 34 | public T getFirst() { return first; } 35 | public T getSecond() { return second; } 36 | public void setFirst(T newValue) { first = newValue; } 37 | public void setSecond(T newValue) { second = newValue; } 38 | 39 | public String toString() { 40 | return "(" + first + ", " + second + ")"; 41 | } 42 | } 43 | class DateInterval extends Pair { 44 | public DateInterval() { super(); } 45 | public DateInterval(LocalDate first, LocalDate second) { 46 | super(); 47 | if(second.compareTo(first) >= 0) { 48 | setFirst(first); 49 | super.setSecond(second); 50 | } else { 51 | System.out.println("second should be Later than first"); 52 | //throw new IllegalArgumentException(); 53 | } 54 | } 55 | public void setSecond(LocalDate second) { 56 | if(second.compareTo(getFirst()) >= 0) 57 | super.setSecond(second); 58 | else { 59 | System.out.println("second should be Later than first"); 60 | //throw new IllegalArgumentException(); 61 | } 62 | } 63 | public LocalDate getSecond() { 64 | System.out.println("LocalDate.getSecond"); 65 | return (LocalDate) super.getSecond(); 66 | } 67 | } -------------------------------------------------------------------------------- /src/第5章继承/5.7反射/ClassReflectAPI.java: -------------------------------------------------------------------------------- 1 | import java.lang.reflect.*; 2 | public class ClassReflectAPI { 3 | public static void main(String[] args) { 4 | // java.lang.Class 5 | // Field[] getFields() 6 | // Field[] getDeclaredFields() 7 | // getFields 方法包含了超类公有域 8 | 9 | // Field getField(String name) 10 | // Field getDeclaredField(String name) 11 | 12 | // Method[] getMethods() 13 | // Method[] getDeclaredMethods() 14 | 15 | // Constructor[] getConstructors() 16 | // Constructor[] getDeclaredConstructors() 17 | 18 | 19 | // java.lang.reflect.Field 20 | // java.lang.reflect.Method 21 | // java.lang.reflect.Constructor 22 | // Class getDecleringClass() 23 | // 返回一个用于描述类中定义的构造器、方法或域的 Class 24 | 25 | // Class[] getExceptionTypes() (Method, Constructor) 26 | // 异常类型的 Class 类数组 27 | 28 | // int getModifiers() 29 | 30 | // String getName() 31 | 32 | // Class[] getParameterTypes() (Method, Constructor) 33 | // 参数类型 34 | 35 | // Class getReturnType() (Method) 36 | // 返回类型 37 | 38 | // Object get(Object obj) (Field) 39 | // 返回 obj 对象中 Field 对象表示的值域 40 | 41 | // void set(Object obj, Object newValue) (Field) 42 | // 设置 obj 对象中 Field 对象表示的值域的值为 newValue 43 | 44 | // public Object invoke(Object implicitParameter, Object... explicitParamenters) 45 | // (Method) 46 | 47 | 48 | // java.lang.reflect.Modifier 49 | // static String toString(int modifiers) 50 | 51 | // static boolean isAbstract(int modifiers) 52 | // static boolean isFinal(int modifiers) 53 | // static boolean isInterface(int modifiers) 54 | // static boolean isNative(int modifiers) 55 | // static boolean isPrivate(int modifiers) 56 | // static boolean isProtected(int modifiers) 57 | // static boolean isPublic(int modifiers) 58 | // static boolean isStatic(int modifiers) 59 | // static boolean isStrict(int modifiers) 60 | // static boolean isSynchronized(int modifiers) 61 | // static boolean isVolatile(int modifiers) 62 | 63 | 64 | // java.lang.reflect.AccessibleObject 65 | // void setAccessible(Boolean flag) 66 | 67 | // boolean isAccessible() 68 | 69 | // static void setAccessible(AccessibleObject[] array, boolean flag) 70 | 71 | 72 | // java.lang.reflect.Array 73 | // static Object get(Object array, int index) 74 | // static xxx getxxx(Object array, int index) 75 | // xxx 是基本类型,返回对应位置的内容 76 | 77 | // static void set(Object array, int index, Object newValue) 78 | // static void setxxx(Object array, int index, xxx newValue) 79 | 80 | // static int getLength(Object array) 81 | 82 | // static Object newInstance(Class componentType, int length) 83 | // static Object newInstance(Class componentType, int[] lengths) 84 | // 返回给定类型,给定维数的数组 85 | } 86 | } -------------------------------------------------------------------------------- /src/第5章继承/5.7反射/ReflectionTest.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | import java.lang.reflect.*; 3 | public class ReflectionTest { 4 | public static void main(String[] args) { 5 | String name; 6 | if(args.length > 0) name = args[0]; 7 | else { 8 | Scanner in = new Scanner(System.in); 9 | System.out.println("Enter class name (e.g. java.util.Date): "); 10 | name = in.next(); 11 | } 12 | 13 | try { 14 | Class cl = Class.forName(name); 15 | Class supercl = cl.getSuperclass(); 16 | String modifiers = Modifier.toString(cl.getModifiers()); 17 | if(modifiers.length() > 0) 18 | System.out.print(modifiers + " "); 19 | System.out.print("class " + name); 20 | 21 | if(supercl != null && supercl != Object.class) 22 | System.out.print(" extends " + supercl.getName()); 23 | System.out.println(" {"); 24 | 25 | printConstructors(cl); 26 | System.out.println(); 27 | 28 | printMethods(cl); 29 | System.out.println(); 30 | 31 | printFields(cl); 32 | System.out.println("}"); 33 | } catch (ClassNotFoundException e) { 34 | e.printStackTrace(); 35 | } 36 | System.exit(0); 37 | } 38 | 39 | public static void printConstructors(Class cl) { 40 | Constructor[] constructors = cl.getConstructors(); 41 | for(Constructor c : constructors) { 42 | String name = c.getName(); 43 | System.out.print(" "); 44 | String modifiers = Modifier.toString(c.getModifiers()); 45 | if(modifiers.length() > 0) 46 | System.out.print(modifiers + " "); 47 | System.out.print(name + "("); 48 | 49 | Class[] paramTypes = c.getParameterTypes(); 50 | for(int j = 0; j < paramTypes.length; j++) { 51 | if(j > 0) System.out.print(", "); 52 | System.out.print(paramTypes[j].getName()); 53 | } 54 | System.out.println(");"); 55 | } 56 | } 57 | 58 | public static void printMethods(Class cl) { 59 | Method[] methods = cl.getMethods(); 60 | for(Method m : methods) { 61 | Class retType = m.getReturnType(); 62 | String name = m.getName(); 63 | System.out.print(" "); 64 | String modifiers = Modifier.toString(m.getModifiers()); 65 | if(modifiers.length() > 0) 66 | System.out.print(modifiers + " "); 67 | System.out.print(retType.getName() + " " + name + "("); 68 | 69 | Class[] paramTypes = m.getParameterTypes(); 70 | for(int j = 0; j < paramTypes.length; j++) { 71 | if(j > 0) System.out.print(", "); 72 | System.out.print(paramTypes[j].getName()); 73 | } 74 | System.out.println(");"); 75 | } 76 | } 77 | 78 | public static void printFields(Class cl) { 79 | Field[] fields = cl.getFields(); 80 | for(Field f : fields) { 81 | Class type = f.getType(); 82 | String name = f.getName(); 83 | System.out.print(" "); 84 | String modifiers = Modifier.toString(f.getModifiers()); 85 | if(modifiers.length() > 0) 86 | System.out.print(modifiers + " "); 87 | System.out.println(type.getName() + " " + name); 88 | 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /src/第8章泛型程序设计/8.9反射和泛型/GenericReflectionTest.java: -------------------------------------------------------------------------------- 1 | import java.lang.reflect.*; 2 | import java.util.*; 3 | 4 | public class GenericReflectionTest { 5 | public static void main(String[] args) { 6 | String name = "java.util.Collection"; 7 | try { 8 | Class cl = Class.forName(name); 9 | printClass(cl); 10 | for(Method m : cl.getDeclaredMethods()) { 11 | printMethod(m); 12 | } 13 | } catch (ClassNotFoundException e) { 14 | e.printStackTrace(); 15 | } 16 | } 17 | 18 | public static void printClass(Class cl) { 19 | System.out.print(cl); 20 | printTypes(cl.getTypeParameters(), "<", ", ", ">", true); 21 | Type sc = cl.getGenericSuperclass(); 22 | if(sc != null) { 23 | System.out.print(" extends "); 24 | printType(sc, false); 25 | } 26 | printTypes(cl.getGenericInterfaces(), " implements ", ", ", "", false); 27 | System.out.println(); 28 | } 29 | 30 | public static void printMethod(Method m) { 31 | String name = m.getName(); 32 | System.out.print(Modifier.toString(m.getModifiers())); 33 | System.out.print(" "); 34 | printTypes(m.getTypeParameters(), "<", ", ", "> ", false); 35 | 36 | printType(m.getGenericReturnType(), false); 37 | System.out.print(" " + name + "("); 38 | printTypes(m.getGenericParameterTypes(), "", ", ", "", false); 39 | System.out.println(")"); 40 | } 41 | 42 | public static void printTypes(Type[] types, String pre, String sep, String suf, boolean isDefinition) { 43 | if(pre.equals(" extends ") && Arrays.equals(types, new Type[]{ Object.class })) 44 | return; 45 | if(types.length > 0) System.out.print(pre); 46 | for(int i = 0; i < types.length; i++) { 47 | if(i > 0) System.out.print(sep); 48 | printType(types[i], isDefinition); 49 | } 50 | if(types.length > 0) System.out.print(suf); 51 | } 52 | 53 | public static void printType(Type type, boolean isDefinition) { 54 | if(type instanceof Class) { 55 | Class t = (Class) type; 56 | System.out.print(t.getName()); 57 | } else if (type instanceof TypeVariable) { 58 | TypeVariable t = (TypeVariable) type; 59 | System.out.print(t.getName()); 60 | if(isDefinition) 61 | printTypes(t.getBounds(), " extends ", " & ", "", false); 62 | } else if (type instanceof WildcardType) { 63 | WildcardType t = (WildcardType) type; 64 | System.out.print("?"); 65 | printTypes(t.getUpperBounds(), " extends ", " & ", "", false); 66 | printTypes(t.getLowerBounds(), " super ", " & ", "", false); 67 | } else if (type instanceof ParameterizedType) { 68 | ParameterizedType t = (ParameterizedType) type; 69 | Type owner = t.getOwnerType(); 70 | if(owner != null) { 71 | printType(owner, false); 72 | System.out.print("."); 73 | } 74 | printType(t.getRawType(), false); 75 | printTypes(t.getActualTypeArguments(), "<", ", ", ">", false); 76 | } else if (type instanceof GenericArrayType) { 77 | GenericArrayType t = (GenericArrayType) type; 78 | //System.out.print(" "); 79 | printType(t.getGenericComponentType(), isDefinition); 80 | System.out.print("[]"); 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /notes/Java核心技术卷一2.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 《Java核心技术卷一》 笔记 2 4 | 5 | 2019.06.11 10:18 6 | 7 | 8 | 9 | ## 第2章 Java程序设计环境 10 | 11 | ### 2.1 安装 Java 开发工具包(JDK) 12 | 13 | JDK: Java Development Kit 14 | 15 | JRE: Java Runtime Environment 16 | 17 | Java SE: Standard Edition 18 | 19 | Java EE: Enterprise Edition 20 | 21 | Java ME: Micro Edition 22 | 23 | 24 | 25 | Java SE 6 对应的内部版本号是 1.6.0 26 | 27 | Java SE 7 -> 1.7.0 28 | 29 | Java SE 8 -> 1.8.0 30 | 31 | 32 | 33 | 并不是所有版本更新都会公开发布 34 | 35 | 36 | 37 | 需要把JDK安装的bin目录加到环境变量 38 | 39 | 可以在终端上输入 40 | 41 | ```shell 42 | javac -version 43 | ``` 44 | 45 | 来判断安装是否成功 46 | 47 | 48 | 49 | ### 2.2 使用命令行工具 50 | 51 | 编写 Welcome.java 52 | 53 | ```java 54 | public class Welcome { 55 | public static void main(String[] args) { 56 | String greeting = "Welcome to Core Java!"; 57 | System.out.println(greeting); 58 | for(int i = 0; i < greeting.length(); i++) 59 | System.out.print("="); 60 | System.out.println(); 61 | } 62 | } 63 | ``` 64 | 65 | 66 | 67 | ```shell 68 | javac Welcome.java 69 | java Welcome 70 | ``` 71 | 72 | 编译并运行Java程序 73 | 74 | javac 命令会编译出一个 .class 字节码文件 75 | 76 | java 命令会用java虚拟机执行字节码文件(其实是指定的类名,所以没有文件后缀) 77 | 78 | 79 | 80 | 注意系统CLASSPATH的设置有时会导致找不到类 81 | 82 | 83 | 84 | ### 2.3 使用集成开发环境 85 | 86 | 书中使用Eclipse 87 | 88 | 89 | 90 | ### 2.4 运行图形化应用程序 91 | 92 | ImageViewer.java 93 | 94 | ```java 95 | import java.awt.*; 96 | import java.io.*; 97 | import javax.swing.*; 98 | 99 | public class ImageViewer { 100 | public static void main(String[] args) { 101 | EventQueue.invokeLater(() -> { 102 | JFrame frame = new ImageViewerFrame(); 103 | frame.setTitle("ImageViewer"); 104 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 105 | frame.setVisible(true); 106 | }); 107 | } 108 | } 109 | 110 | class ImageViewerFrame extends JFrame { 111 | private JLabel label; 112 | private JFileChooser chooser; 113 | private static final int DEFAULT_WIDTH = 300; 114 | private static final int DEFAULT_HEIGHT = 400; 115 | 116 | public ImageViewerFrame() { 117 | setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); 118 | label = new JLabel(); 119 | add(label); 120 | 121 | chooser = new JFileChooser(); 122 | chooser.setCurrentDirectory(new File(".")); 123 | 124 | JMenuBar menuBar = new JMenuBar(); 125 | setJMenuBar(menuBar); 126 | 127 | JMenu menu = new JMenu("File"); 128 | menuBar.add(menu); 129 | 130 | JMenuItem openItem = new JMenuItem("Open"); 131 | menu.add(openItem); 132 | 133 | openItem.addActionListener(event -> { 134 | int result = chooser.showOpenDialog(null); 135 | if(result == JFileChooser.APPROVE_OPTION) 136 | { 137 | String name = chooser.getSelectedFile().getPath(); 138 | label.setIcon(new ImageIcon(name)); 139 | } 140 | }); 141 | 142 | JMenuItem exitItem = new JMenuItem("Exit"); 143 | menu.add(exitItem); 144 | exitItem.addActionListener(event -> System.exit(0)); 145 | } 146 | } 147 | ``` 148 | 149 | 可以选一个图片并显示出来 150 | 151 | 152 | 153 | ### 2.5 构建并运行 applet * 154 | 155 | (未完成) 156 | 157 | RoadApplet.java 158 | 159 | RoadApplet.html 160 | 161 | 162 | 163 | ```shell 164 | javac RoadApplet.java 165 | jar cvfm RoadApplet.jar RoadApplet.mf *.class 166 | appletviewer RoadApplet.html 167 | ``` 168 | 169 | 170 | 171 | 注意HTML中的\标签 172 | 173 | ```html 174 | 176 | 177 | ``` 178 | 179 | appletviewer会忽略这个标签以外的内容 180 | 181 | 浏览器需要支持java并设置好java信任本地applet才可以运行查看 182 | 183 | -------------------------------------------------------------------------------- /src/第5章继承/5.7反射/ClassNameTest.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class ClassNameTest { 4 | public static void main(String[] args) { 5 | Class cl1 = Random.class; 6 | Class cl2 = int.class; 7 | Class cl3 = Double[].class; 8 | Class cl4 = Employee.class; 9 | Class cl5 = Employee[].class; 10 | System.out.println("Random.class : " + cl1.getName()); 11 | System.out.println("int.class : " + cl2.getName()); 12 | System.out.println("Double[].class : " + cl3.getName()); 13 | System.out.println("Employee.class : " + cl4.getName()); 14 | System.out.println("Employee[].class : " + cl5.getName()); 15 | 16 | System.out.println("\n========================\n"); 17 | 18 | System.out.println("short.class : " + short.class.getName()); 19 | System.out.println("byte.class : " + byte.class.getName()); 20 | System.out.println("int.class : " + int.class.getName()); 21 | System.out.println("long.class : " + long.class.getName()); 22 | System.out.println("float.class : " + float.class.getName()); 23 | System.out.println("double.class : " + double.class.getName()); 24 | System.out.println("char.class : " + char.class.getName()); 25 | System.out.println("boolean.class : " + boolean.class.getName()); 26 | System.out.println("void.class : " + void.class.getName()); 27 | 28 | System.out.println("\n========================\n"); 29 | 30 | System.out.println("short[].class : " + short[].class.getName()); 31 | System.out.println("byte[].class : " + byte[].class.getName()); 32 | System.out.println("int[].class : " + int[].class.getName()); 33 | System.out.println("long[].class : " + long[].class.getName()); 34 | System.out.println("float[].class : " + float[].class.getName()); 35 | System.out.println("double[].class : " + double[].class.getName()); 36 | System.out.println("char[].class : " + char[].class.getName()); 37 | System.out.println("boolean[].class : " + boolean[].class.getName()); 38 | //System.out.println("void[].class : " + void[].class.getName()); 39 | 40 | System.out.println("\n========================\n"); 41 | 42 | System.out.println("Short.class : " + Short.class.getName()); 43 | System.out.println("Byte.class : " + Byte.class.getName()); 44 | System.out.println("Integer.class : " + Integer.class.getName()); 45 | System.out.println("Long.class : " + Long.class.getName()); 46 | System.out.println("Float.class : " + Float.class.getName()); 47 | System.out.println("Double.class : " + Double.class.getName()); 48 | System.out.println("Character.class : " + Character.class.getName()); 49 | System.out.println("Boolean.class : " + Boolean.class.getName()); 50 | System.out.println("Void.class : " + Void.class.getName()); 51 | 52 | System.out.println("\n========================\n"); 53 | 54 | System.out.println("Short[].class : " + Short[].class.getName()); 55 | System.out.println("Byte[].class : " + Byte[].class.getName()); 56 | System.out.println("Int[].class : " + Integer[].class.getName()); 57 | System.out.println("Long[].class : " + Long[].class.getName()); 58 | System.out.println("Float[].class : " + Float[].class.getName()); 59 | System.out.println("Double[].class : " + Double[].class.getName()); 60 | System.out.println("Char[].class : " + Character[].class.getName()); 61 | System.out.println("Boolean[].class : " + Boolean[].class.getName()); 62 | System.out.println("Void[].class : " + Void[].class.getName()); 63 | } 64 | } 65 | 66 | class Employee { 67 | 68 | } -------------------------------------------------------------------------------- /src/第8章泛型程序设计/8.8通配符类型/PairTest3.java: -------------------------------------------------------------------------------- 1 | import java.time.*; 2 | 3 | public class PairTest3 { 4 | public static void main(String[] args) { 5 | Manager ceo = new Manager("Gus Greedy", 800000, 2003, 12, 15); 6 | Manager cfo = new Manager("Sid Sneaky", 600000, 2003, 12, 15); 7 | Pair buddies = new Pair<>(ceo,cfo); 8 | printBuddies(buddies); 9 | ceo.setBonus(1000000); 10 | cfo.setBonus(500000); 11 | 12 | Manager[] managers = {ceo, cfo}; 13 | Pair result = new Pair<>(); 14 | minmaxBonus(managers, result); 15 | printBuddies(result); 16 | maxminBonus(managers, result); 17 | printBuddies(result); 18 | } 19 | 20 | public static void printBuddies(Pair p) { 21 | Employee first = p.getFirst(); 22 | Employee second = p.getSecond(); 23 | System.out.println(first.getName() + " and " + second.getName() + " are buddies."); 24 | } 25 | public static void minmaxBonus(Manager[] a, Pair result) { 26 | if(a.length == 0) return; 27 | Manager min = a[0]; 28 | Manager max = a[0]; 29 | for(int i = 1; i < a.length; i++) { 30 | if(min.getBonus() > a[i].getBonus()) min = a[i]; 31 | if(max.getBonus() < a[i].getBonus()) max = a[i]; 32 | } 33 | result.setFirst(min); 34 | result.setSecond(max); 35 | } 36 | public static void maxminBonus(Manager[] a, Pair result) { 37 | minmaxBonus(a,result); 38 | //PairAlg.swap(result); 39 | PairAlg.swapHelper(result); 40 | } 41 | } 42 | 43 | class Pair { 44 | private T first; 45 | private T second; 46 | public Pair() { first = null; second = null; } 47 | public Pair(T first, T second) { 48 | this.first = first; 49 | this.second = second; 50 | } 51 | public T getFirst() { return first; } 52 | public T getSecond() { return second; } 53 | public void setFirst(T newValue) { first = newValue; } 54 | public void setSecond(T newValue) { second = newValue; } 55 | } 56 | 57 | class PairAlg { 58 | public static boolean hasNulls(Pair p) { 59 | return p.getFirst() == null || p.getSecond() == null; 60 | } 61 | public static void swap(Pair p) { 62 | swapHelper(p); 63 | } 64 | public static void swapHelper(Pair p) { 65 | T t = p.getFirst(); 66 | p.setFirst(p.getSecond()); 67 | p.setSecond(t); 68 | } 69 | } 70 | 71 | class Employee { 72 | private String name; 73 | private double salary; 74 | private LocalDate hireDay; 75 | public Employee(String n, double s, int year, int month, int day) { 76 | name = n; 77 | salary = s; 78 | hireDay = LocalDate.of(year, month, day); 79 | } 80 | public String getName() { 81 | return name; 82 | } 83 | public double getSalary() { 84 | return salary; 85 | } 86 | public LocalDate getHireDay() { 87 | return hireDay; 88 | } 89 | public void raiseSalary(double byPercent) { 90 | double raise = salary * byPercent / 100; 91 | salary += raise; 92 | } 93 | } 94 | class Manager extends Employee { 95 | private double bonus; 96 | 97 | public Manager(String name, double salary, int year, int month, int day) { 98 | super(name, salary, year, month, day); 99 | bonus = 0; 100 | } 101 | 102 | void setBonus(double bonus) { 103 | this.bonus = bonus; 104 | } 105 | 106 | public double getBonus() { 107 | return bonus; 108 | } 109 | 110 | public double getSalary() { 111 | return super.getSalary() + bonus; 112 | } 113 | } -------------------------------------------------------------------------------- /src/第9章集合/9.4视图与包装器/CollectionsAPI.java: -------------------------------------------------------------------------------- 1 | public class CollectionsAPI { 2 | public static void main(String[] args) { 3 | // java.util.Collections 4 | // static Collection unmodifiableCollection(Collection c) 5 | // static List unmodifiableList(List c) 6 | // static Set unmodifiableSet(Set c) 7 | // static SortedSet unmodifiableSortedSet(SortedSet c) 8 | // static SortedSet unmodifiableNavigableSet(NavigableSet c) 9 | // static Map unmodifiableMap(Map c) 10 | // static SortedMap unmodifiableSortedMap(SortedMap c) 11 | // static SortedMap unmodifiableNavigableMap(NavigableMap c) 12 | // 构建视图,更改器方法抛出 UnsupportedOperationException 13 | 14 | // static Collection synchronizedCollection(Collection c) 15 | // static List synchronizedList(List c) 16 | // static Set synchronizedSet(Set c) 17 | // static SortedSet synchronizedSortedSet(SortedSet c) 18 | // static SortedSet synchronizedNavigableSet(NavigableSet c) 19 | // static Map synchronizedMap(Map c) 20 | // static SortedMap synchronizedSortedMap(SortedMap c) 21 | // static SortedMap synchronizedNavigableMap(NavigableMap c) 22 | // 构建视图,视图的方法同步 23 | 24 | // static Collection checkedCollection(Collection c, Class elementType) 25 | // static List checkedList(List c, Class elementType) 26 | // static Set checkedSet(Set c, Class elementType) 27 | // static SortedSet checkedSortedSet(SortedSet c, Class elementType) 28 | // static SortedSet checkedNavigableSet(NavigableSet c, Class elementType) 29 | // static Map checkedMap(Map c, Class keyType, Class valueType) 30 | // static SortedMap checkedSortedMap(SortedMap c, Class keyType, Class valueType) 31 | // static SortedMap checkedNavigableMap(NavigableMap c, Class keyType, Class valueType) 32 | // static Queue checkedQueue(Queue queue, Class elementType) 33 | // 构建视图,插入错误类型的元素将抛出 ClassCastException 34 | 35 | // static List nCopies(int n, E value) 36 | // static Set singleton(E value) 37 | // static List singletonList(E value) 38 | // static Map singletonMap(K key, V value) 39 | 40 | // static List emptyList() 41 | // static Set emptySet() 42 | // static SortedSet emptySortedSet() 43 | // static NavigableSet emptyNavigableSet() 44 | // static Map emptyMap() 45 | // static SortedMap emptySortedMap() 46 | // static NavigableMap emptyNavigableMap() 47 | // static Enumeration emptyEnumeration() 48 | // static Iterator emptyIterator() 49 | // static ListIterator emptyListIterator() 50 | 51 | 52 | // java.util.Arrays 53 | // static List asList(E... array) 54 | 55 | 56 | // java.util.List 57 | // List subList(int firstIncluded, int firstExcluded) 58 | 59 | 60 | // java.util.SortedSet 61 | // SortedList subSet(E firstIncluded, E firstExcluded) 62 | // SortedList headSet(E firstExcluded) 63 | // SortedList tailSet(E firstIncluded) 64 | 65 | 66 | // java.util.NavigableSet 67 | // NavigableSet subSet(E from, boolean fromInclusive, E to, boolean toInclusive) 68 | // NavigableSet headSet(E to, boolean toInclusive) 69 | // NavigableSet tailSet(E from, boolean fromInclusive) 70 | 71 | 72 | // java.util.SortedMap 73 | // SortedMap subMap(K firstIncluded, K firstExcluded) 74 | // SortedMap headMap(K firstExcluded) 75 | // SortedMap tailMap(K firstIncluded) 76 | 77 | 78 | // java.util.NavigableMap 79 | // NavigableSortedMap subMap(K firstIncluded, K firstExcluded) 80 | // NavigableSortedMap headMap(K firstExcluded) 81 | // NavigableSortedMap tailMap(K firstIncluded) 82 | } 83 | } -------------------------------------------------------------------------------- /notes/Java核心技术卷一6_3.md: -------------------------------------------------------------------------------- 1 | # 《Java核心技术卷一》 笔记 6_3 2 | 3 | 2019.06.25 14:30 4 | 5 | 6 | 7 | ## 第6章 接口、lambda 表达式与内部类 8 | 9 | ### 6.5 代理(proxy) 10 | 11 | 利用代理可以在运行时创建一个实现了一组给定接口的新类 12 | 13 | 这种功能只有在编译时无法确定需要实现哪个接口时才有必要使用 14 | 15 | 16 | 17 | #### 6.5.1 何时使用代理 18 | 19 | 表示接口的对象,确切类型在编译时无法知道,构造实现接口的类就需要使用 newInstance 方法或使用反射机制找出类的构造器。但是不能实例化接口,需要在运行时定义新类。 20 | 21 | 可以使用程序生成代码到文件再编译文件后加载,但是这样做速度比较慢。 22 | 23 | 代理类包含接口所需要的全部方法,Object 类的全部方法 24 | 25 | 26 | 27 | 不能在运行时定义方法的新代码,而是提供一个调用处理器(invocation handler) 28 | 29 | 调用处理器是实现了 InvocationHandler 接口的类。 30 | 31 | 接口中只有一个方法 32 | 33 | ```java 34 | Object invoke(Object proxy, Method method, Object[] args); 35 | ``` 36 | 37 | 无论何时调用代理对象的方法,调用处理器的 invoke 方法都会被调用,并向其传递 Method 对象和原始的调用参数。调用处理器必须给出处理调用的方式 38 | 39 | 40 | 41 | #### 6.5.2 创建代理对象 42 | 43 | 想创建一个代理对象,需要使用 Proxy 类的 newProxyInstance 方法 44 | 45 | 这个方法有 3 个参数 46 | 47 | 一个类加载器(class loader),目前用 null 默认加载器 48 | 49 | 一个 Class 对象数组,每个元素都是需要实现的接口 50 | 51 | 一个调用处理器 52 | 53 | 54 | 55 | 使用代理可能的目的: 56 | 57 | 路由对远程服务器的方法调用 58 | 59 | 在程序运行期间,将用户接口事件与动作关联起来 60 | 61 | 为调试,跟踪方法调用 62 | 63 | 64 | 65 | ProxyTest.java 66 | 67 | ```java 68 | import java.lang.reflect.*; 69 | import java.util.*; 70 | 71 | public class ProxyTest { 72 | public static void main(String[] args) { 73 | Object[] elements = new Object[1000]; 74 | for(int i = 0; i < elements.length; i++) { 75 | Integer value = i + 1; 76 | InvocationHandler handler = new TraceHandler(value); 77 | Object proxy = Proxy.newProxyInstance(null, new Class[]{Comparable.class}, handler); 78 | elements[i] = proxy; 79 | } 80 | 81 | Integer key = new Random().nextInt(elements.length) + 1; 82 | int result = Arrays.binarySearch(elements, key); 83 | if(result >= 0) 84 | System.out.println(elements[result]); 85 | } 86 | } 87 | 88 | class TraceHandler implements InvocationHandler { 89 | private Object target; 90 | public TraceHandler(Object t) { 91 | target = t; 92 | } 93 | public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { 94 | System.out.print(target); 95 | System.out.print("." + m.getName() + "("); 96 | if(args != null) { 97 | for(int i = 0; i < args.length; i++) { 98 | System.out.print(args[i]); 99 | if(i < args.length - 1) System.out.print(", "); 100 | } 101 | } 102 | System.out.println(")"); 103 | return m.invoke(target, args); 104 | } 105 | } 106 | ``` 107 | 108 | 结果 109 | 110 | ```text 111 | 500.compareTo(672) 112 | 750.compareTo(672) 113 | 625.compareTo(672) 114 | 687.compareTo(672) 115 | 656.compareTo(672) 116 | 671.compareTo(672) 117 | 679.compareTo(672) 118 | 675.compareTo(672) 119 | 673.compareTo(672) 120 | 672.compareTo(672) 121 | 672.toString() 122 | 672 123 | ``` 124 | 125 | 126 | 127 | #### 6.5.3 代理类的特性 128 | 129 | 代理类是运行时创建的,一旦被创建就和普通类没有区别了。 130 | 131 | 所有代理类都扩展于 Proxy 类。一个代理类只有一个实例域,调用处理器,它定义在 Proxy 的超类中。为了履行代理对象的职责,所需要的任何附加数据都必须存储在调用处理器中。 132 | 133 | 134 | 135 | 所有的代理类都覆盖了 Object 类的 toString,equals 和 hashCode 方法 136 | 137 | 这些方法和其他代理方法一样仅仅调用了调用处理器的 invoke。Object 类中的其他方法没有被定义 138 | 139 | 没有定义代理类的名字,虚拟机将自动生成一个以 $Proxy 开头的类名 140 | 141 | 142 | 143 | 对于特定的类加载器和预设的一组接口,只能有一个代理类,多次调用 newProxyInstance 只是得到了同一个类的不同对象。 144 | 145 | 可以利用 getProxyClass 得到这个类 146 | 147 | ```java 148 | Class proxyClass = Proxy.getProxyClass(null, interface); 149 | ``` 150 | 151 | 152 | 153 | 代理类一定是 public 和 final 的。如果代理类的所有接口都是 public,代理类就不属于某个特定包 154 | 155 | 否则所有非公有接口必须属于同一个包,同时代理类也属于这个包 156 | 157 | 通过调用 Proxy 类中的 isProxyClass 方法检测一个特定的 Class 对象是否代表一个代理类 158 | 159 | 160 | 161 | ProxyAPI.java 162 | 163 | ```java 164 | public class ProxyAPI { 165 | public static void main(String[] args) { 166 | // java.lang.reflect.InvocationHandler 167 | // Object invoke(Object proxy, Mehtod method, Object[] args) 168 | // 定义了代理对象调用方法时希望执行的操作 169 | 170 | // java.lang.reflect.Proxy 171 | // static Class getProxyClass(ClassLoader loader, Class... interfaces) 172 | // 返回实现指定接口的代理类 173 | 174 | // static Object newProxyInstance(ClassLoader loader, Class[] interface, InvocationHandler handler) 175 | // 构造实现指定接口的代理类的一个实例 176 | // 所有方法都会调用给定处理器对象的 invoke 方法 177 | 178 | // static boolean isProxyClass(Class cl) 179 | // cl 是代理类则返回 true 180 | } 181 | } 182 | ``` -------------------------------------------------------------------------------- /notes/Java核心技术卷一7_0.md: -------------------------------------------------------------------------------- 1 | # 《Java核心技术卷一》 笔记 7_0 2 | 3 | 2019.06.25 15:53 4 | 5 | 6 | 7 | ## 第7章 异常、断言和日志 8 | 9 | 程序总是会出现 bug 的,输入也不一定合法,打开文件也不一定存在,这就需要一套处理问题的机制。 10 | 11 | 为了避免用户数据丢失,应该: 12 | 13 | 向用户通告错误 14 | 15 | 保存所有的工作结果 16 | 17 | 允许用户以妥善形式退出程序 18 | 19 | 20 | 21 | Java 使用一种称为异常处理(exception handling)的机制。 22 | 23 | Java 可以通过断言不必要在调试结束后将测试删掉,重新调试时再将代码粘贴回来 24 | 25 | 26 | 27 | 程序出错时并不总是能够与用户或中断进行沟通,此时希望记录下出现的问题,以便日后分析,可以使用 Java 日志框架 28 | 29 | 30 | 31 | ### 7.1 处理错误 32 | 33 | 检测和引发错误的代码通常离恢复数据、保存用户操作并正常退出的代码很远 34 | 35 | 异常处理的任务就是将控制权从错误产生的地方转移给能处理这种错误的处理器 36 | 37 | 38 | 39 | 错误与异常原因 40 | 41 | 1.用户输入错误。不正确使用,意外错误输入 42 | 43 | 2.设备错误。硬件问题 44 | 45 | 3.物理限制。磁盘满 46 | 47 | 4.代码错误。传统方法是返回特殊的错误码,但是有的时候无法使用错误码 48 | 49 | 50 | 51 | Java 方法无法正常完成任务时,可以通过另一个路径退出方法。这种情况,方法会立即退出,不产生返回值,而是抛出(throw)一个封装了错误信息的对象。调用此方法的方法也无法继续执行,而是异常处理机制开始搜索能够处理这种异常状况的异常处理器(Exception Handler) 52 | 53 | 异常具有自己的语法和特定的继承结构 54 | 55 | 56 | 57 | #### 7.1.1 异常分类 58 | 59 | 异常都是派生于 Throwable 类的实例。 60 | 61 | Java 内置的异常类不能满足需求时,用户可以自己创建异常类 62 | 63 | ```text 64 | Throwable <- - Error 65 | | 66 | - Exception <- - IOException 67 | | 68 | - RuntimeException 69 | ``` 70 | 71 | 72 | 73 | Error 描述了 Java 运行时系统内部的错误和资源耗尽错误,应用程序不应该抛出这个类型的对象。 74 | 75 | 出现这样的错误应当通知用户,并尽力使程序安全的终止,此外就无能为力了。 76 | 77 | 78 | 79 | 设计 Java 程序主要关注 Exception 层次 80 | 81 | 其中应用程序本身的错误应该关注 RuntimeException 应用程序本身没有问题则关注 IOException 82 | 83 | 派生于 RuntimeException 的异常: 84 | 85 | 错误的类型转换 86 | 87 | 数组访问越界 88 | 89 | 访问 null 指针 90 | 91 | 不是派生于 RuntimeException 的异常: 92 | 93 | 试图在文件尾后面读取数据 94 | 95 | 试图打开一个不存在的文件 96 | 97 | 试图根据给定字符串查找 Class 对象,但字符串表示的类不存在 98 | 99 | 100 | 101 | Java 语言规范将派生于 Error 和 RuntimeException 类的所有异常称为非受查(unchecked)异常,其他所有异常称为受查(checked)异常。编译器将检查是否为所有受查异常提供了异常处理器。 102 | 103 | 104 | 105 | C++ 中 logic_error 对应 Java 的 RuntimeException 而 runtime_error 对应 其他的异常 106 | 107 | 108 | 109 | #### 7.1.2 声明受查异常 110 | 111 | 如果遇到了无法处理的情况,那么 Java 方法可以抛出一个异常。 112 | 113 | 一个方法不仅要告诉编译器将要返回什么值,还要告诉编译器有可能发生什么错误。 114 | 115 | 方法应该在首部声明所有可能抛出的异常 116 | 117 | ```java 118 | public FileInputStream(String name) throws FileNotFoundException 119 | ``` 120 | 121 | 构造器可能无法根据给定的参数产生 FileInputStream 对象,如果这样的情况发生,就不会初始化一个对象,而是抛出一个异常。 122 | 123 | 124 | 125 | 自己编写方法时不必将所有可能抛出的异常都进行声明。 126 | 127 | 以下 4 种情况应该抛出异常: 128 | 129 | 调用一个抛出受查异常的方法 130 | 131 | 程序运行过程中发现错误,并利用 throw 语句抛出一个受查异常 132 | 133 | 程序出现错误 134 | 135 | Java 虚拟机和运行时库出现内部错误 136 | 137 | 138 | 139 | 其中前两种情况必须告诉调用方法的程序员可能会抛出异常。如果没有异常处理器捕获这个异常,当前执行的线程就会结束。 140 | 141 | 应当根据异常规范(exception specification)在首部声明该方法可能抛出的异常 142 | 143 | 如果一个方法可能抛出多种异常可以用逗号分隔 144 | 145 | 146 | 147 | 不需要声明 Java 的内部错误,我们无法控制和处理这些异常。 148 | 149 | 不应该声明 RuntimeException 继承的非受查异常,这些运行时错误完全在我们的控制之下,应当通过代码尽量避免。 150 | 151 | 152 | 153 | 除了声明异常也可以捕获异常,这样异常不会被抛到方法外,也不需要 throws 规范。 154 | 155 | 156 | 157 | Java 的 throws 说明符与 C++ 中的 throw 说明符基本类似。C++ 中 throw 说明符在运行时执行,而不是编译时,C++ 编译器不处理任何异常规范,如果函数抛出的异常没有出现在 throw 列表中,就会调用 unexcepted 函数,这个函数默认处理方式是终止程序执行。C++ 中如果没给出 throw 说明,函数可能抛出任何异常。Java 中如果没有 throws 说明符,方法将不能抛出任何受查异常。 158 | 159 | 160 | 161 | #### 7.1.3 如何抛出异常 162 | 163 | 如读文件超过了 EOF 标记 164 | 165 | 抛出异常的语句为 166 | 167 | ```java 168 | throw new EOFException(); 169 | ``` 170 | 171 | 例子 172 | 173 | ```java 174 | String readData(Scanner in) throws EOFException { 175 | ... 176 | while(!in.hasNext()) { 177 | if(n < len) 178 | throw new EOFException(); 179 | } 180 | return s; 181 | } 182 | ``` 183 | 184 | EOFException 还有一个含有字符串参数的构造器,可以传递更详细的异常信息 185 | 186 | 对于一个已经存在的异常类,将其抛出: 187 | 188 | 找到合适的异常类,创建该类对象,将对象抛出 189 | 190 | 191 | 192 | Java 中只能抛出 Throwable 的子类,C++ 可以抛出任何值 193 | 194 | 195 | 196 | #### 7.1.4 创建异常类 197 | 198 | 在程序中可能遇到任何标准异常类都没有充分描述的问题,此时需要创建新的异常类 199 | 200 | 创建的异常类应该继承一个 Exception 类。 201 | 202 | 习惯上,定义的类应该包含两个构造器,一个默认构造器,一个带有详细描述信息的构造器 203 | 204 | 超类 Throwable 的 toString 可以打印这些信息 205 | 206 | ```java 207 | class FileFormatException extends IOException { 208 | public FileFormatException(){} 209 | public FileFormatException(String gripe) { 210 | super(gripe); 211 | } 212 | } 213 | ``` 214 | 215 | 使用上面的异常 216 | 217 | ```java 218 | String readData(BufferedRead in) throws FileFormatException { 219 | while(...) { 220 | if(ch == -1) { // EOF 221 | if(n < len) 222 | throw new FileFormatException(); 223 | } 224 | } 225 | } 226 | ``` 227 | 228 | ThrowableAPI.java 229 | 230 | ```java 231 | public class ThrowableAPI { 232 | public static void main(String[] args) { 233 | // java.lang.Throwable 234 | // Throwable() 235 | 236 | // Throwable(String message) 237 | // 附带详细信息 238 | 239 | // String getMessage() 240 | // 获得 Throwable 对象的详细信息 241 | } 242 | } 243 | ``` 244 | 245 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 《Java核心编程:卷一》笔记 2 | 3 | 书中核心知识的整理 4 | 5 | 书中大部分源码(部分源码有所更改) 6 | 7 | 整理书中的 API 到程序 8 | 9 | 部分补充测试代码块 10 | 11 | 给出所有跑过的代码的运行结果 12 | 13 | 14 | 15 | ## 按章节笔记目录 16 | 17 | ### [前言](/notes/Java核心技术卷一0.md) 18 | 19 | ### [第 1 章 Java 程序设计概述](/notes/Java核心技术卷一1.md) 20 | 21 | [1.1 Java程序设计平台](/notes/Java核心技术卷一1.md#11-java程序设计平台) 22 | 23 | [1.2 Java “白皮书”的关键术语](/notes/Java核心技术卷一1.md#12-java-白皮书的关键术语) 24 | 25 | [1.3 Java applet 与 Internet](/notes/Java核心技术卷一1.md#13-java-applet-与-internet) 26 | 27 | [1.4 Java发展简史](/notes/Java核心技术卷一1.md#14-java发展简史) 28 | 29 | [1.5 关于 Java 的常见误解](/notes/Java核心技术卷一1.md#15-关于-java-的常见误解) 30 | 31 | ### [第 2 章 Java 程序设计环境](/notes/Java核心技术卷一2.md) 32 | 33 | [2.1 安装 Java 开发工具包(JDK)](/notes/Java核心技术卷一2.md#21-安装-java-开发工具包jdk) 34 | 35 | [2.2 使用命令行工具](/notes/Java核心技术卷一2.md#22-使用命令行工具) 36 | 37 | [2.3 使用集成开发环境](/notes/Java核心技术卷一2.md#23-使用集成开发环境) 38 | 39 | [2.4 运行图形化应用程序](/notes/Java核心技术卷一2.md#24-运行图形化应用程序) 40 | 41 | [2.5 构建并运行 applet *](/notes/Java核心技术卷一2.md#25-构建并运行-applet-) 42 | 43 | ### [第 3 章 Java 的基本程序设计结构](/notes/Java核心技术卷一3_0.md) 44 | 45 | [3.1 一个简单的 Java 应用程序](/notes/Java核心技术卷一3_0.md#31-一个简单的-java-应用程序) 46 | 47 | [3.2 注释](/notes/Java核心技术卷一3_0.md#32-注释) 48 | 49 | [3.3 数据类型](/notes/Java核心技术卷一3_0.md#33-数据类型) 50 | 51 | [3.4 变量](/notes/Java核心技术卷一3_0.md#34-变量) 52 | 53 | [3.5 运算符](/notes/Java核心技术卷一3_0.md#35-运算符) 54 | 55 | [3.6 字符串](/notes/Java核心技术卷一3_1.md#36-字符串) 56 | 57 | [3.7 输入输出](/notes/Java核心技术卷一3_1.md#37-输入输出) 58 | 59 | [3.8 控制流程](/notes/Java核心技术卷一3_2.md#38-控制流程) 60 | 61 | [3.9 大数值](/notes/Java核心技术卷一3_2.md#39-大数值) 62 | 63 | [3.10 数组](/notes/Java核心技术卷一3_2.md#310-数组) 64 | 65 | ### [第 4 章 对象与类](/notes/Java核心技术卷一4_0.md) 66 | 67 | [4.1 面向对象程序设计(OOP)概述](/notes/Java核心技术卷一4_0.md#41-面向对象程序设计oop概述) 68 | 69 | [4.2 使用预定义类](/notes/Java核心技术卷一4_0.md#42-使用预定义类) 70 | 71 | [4.3 用户自定义类](/notes/Java核心技术卷一4_0.md#43-用户自定义类) 72 | 73 | [4.4 静态域与静态方法](/notes/Java核心技术卷一4_1.md#44-静态域与静态方法) 74 | 75 | [4.5 方法参数](/notes/Java核心技术卷一4_1.md#45-方法参数) 76 | 77 | [4.6 对象构造](/notes/Java核心技术卷一4_1.md#46-对象构造) 78 | 79 | [4.7 包](/notes/Java核心技术卷一4_2.md#47-包) 80 | 81 | [4.8 类路径](/notes/Java核心技术卷一4_2.md#48-类路径) 82 | 83 | [4.9 文档注释](/notes/Java核心技术卷一4_2.md#49-文档注释) 84 | 85 | [4.10 类设计技巧](/notes/Java核心技术卷一4_2.md#410-类设计技巧) 86 | 87 | ### [第 5 章 继承(Inheritance)](/notes/Java核心技术卷一5_0.md) 88 | 89 | [5.1 类、超类和子类](/notes/Java核心技术卷一5_0.md#51-类超类和子类) 90 | 91 | [5.2 Object:所有类的超类](/notes/Java核心技术卷一5_1.md#52-object所有类的超类) 92 | 93 | [5.3 泛型数组列表](/notes/Java核心技术卷一5_2.md#53-泛型数组列表) 94 | 95 | [5.4 对象包装器与自动装箱](/notes/Java核心技术卷一5_2.md#54-对象包装器与自动装箱) 96 | 97 | [5.5 参数数量可变的方法](/notes/Java核心技术卷一5_2.md#55-参数数量可变的方法) 98 | 99 | [5.6 枚举类](/notes/Java核心技术卷一5_2.md#56-枚举类) 100 | 101 | [5.7 反射(reflective)](/notes/Java核心技术卷一5_3.md#57-反射reflective) 102 | 103 | [5.8 继承的设计技巧](/notes/Java核心技术卷一5_3.md#58-继承的设计技巧) 104 | 105 | ### [第 6 章 接口、lambda 表达式与内部类](/notes/Java核心技术卷一6_0.md) 106 | 107 | [6.1 接口](/notes/Java核心技术卷一6_0.md#61-接口) 108 | 109 | [6.2 接口示例](/notes/Java核心技术卷一6_0.md#62-接口示例) 110 | 111 | [6.3 lambda 表达式](/notes/Java核心技术卷一6_1.md#6.3-lambda-表达式) 112 | 113 | [6.4 内部类(inner class)](/notes/Java核心技术卷一6_2.md#64-内部类inner-class) 114 | 115 | [6.5 代理(proxy)](/notes/Java核心技术卷一6_3.md#65-代理proxy) 116 | 117 | ### [第 7 章 异常、断言和日志](/notes/Java核心技术卷一7_0.md) 118 | 119 | [7.1 处理错误](/notes/Java核心技术卷一7_0.md#71-处理错误) 120 | 121 | [7.2 捕获异常](/notes/Java核心技术卷一7_1.md#72-捕获异常) 122 | 123 | [7.3 使用异常机制的技巧](/notes/Java核心技术卷一7_1.md#73-使用异常机制的技巧) 124 | 125 | [7.4 使用断言](/notes/Java核心技术卷一7_2.md#74-使用断言) 126 | 127 | [7.5 记录日志*](/notes/Java核心技术卷一7_2.md#75-记录日志) 128 | 129 | ### [第 8 章 泛型程序设计](/notes/Java核心技术卷一8_0.md) 130 | 131 | [8.1 为什么要使用泛型程序设计](/notes/Java核心技术卷一8_0.md#81-为什么要使用泛型程序设计) 132 | 133 | [8.2 定义简单的泛型类](/notes/Java核心技术卷一8_0.md#82-定义简单的泛型类) 134 | 135 | [8.3 泛型方法](/notes/Java核心技术卷一8_0.md#83-泛型方法) 136 | 137 | [8.4 类型变量的限定](/notes/Java核心技术卷一8_0.md#84-类型变量的限定) 138 | 139 | [8.5 泛型代码和虚拟机](/notes/Java核心技术卷一8_0.md#85-泛型代码和虚拟机) 140 | 141 | [8.6 约束与局限性](/notes/Java核心技术卷一8_1.md#86-约束与局限性) 142 | 143 | [8.7 泛型类型的继承规则](/notes/Java核心技术卷一8_1.md#87-泛型类型的继承规则) 144 | 145 | [8.8 通配符类型](/notes/Java核心技术卷一8_2.md#88-通配符类型) 146 | 147 | [8.9 反射和泛型](/notes/Java核心技术卷一8_3.md#89-反射和泛型) 148 | 149 | ### [第 9 章 集合](/notes/Java核心技术卷一9_0.md) 150 | 151 | [9.1 Java 集合框架](/notes/Java核心技术卷一9_0.md#91-Java-集合框架) 152 | 153 | [9.2 具体的集合](/notes/Java核心技术卷一9_1.md#92-具体的集合) 154 | 155 | [9.3 映射](/notes/Java核心技术卷一9_2.md#93-映射map) 156 | 157 | [9.4 视图与包装器](/notes/Java核心技术卷一9_2.md#94-视图与包装器) 158 | 159 | [9.5 算法](/notes/Java核心技术卷一9_3.md#95-算法) 160 | 161 | ## 重点内容 162 | 163 | 这里并不整理一般意义下的骨架型重点内容 164 | 165 | 总结一些比较反常识的关键词,不容易望文生义的关键词,或与其他语言(特别是 C++)不太一致的特性 166 | 167 | 168 | 169 | ### Java 函数函数参数只有按值传递 170 | 171 | 章节:4.5 172 | 173 | 笔记位置:[4_1](/notes/Java核心技术卷一4_1.md#45-方法参数) 174 | 175 | 代码:[ParamTest.java](/src/第4章对象与类/4.5方法参数/ParamTest.java) 176 | 177 | 178 | ### 深拷贝与浅拷贝 179 | 180 | 章节:6.2.3 181 | 182 | 笔记位置:[6_0](/notes/Java核心技术卷一6_0.md#623-对象克隆) 183 | 184 | 代码:[CloneTest.java](/src/第6章接口lambda表达式与内部类/6.2接口示例/cloneTest) 185 | 186 | 187 | 188 | ### Lambda 表达式 189 | 190 | 章节:6.3 191 | 192 | 笔记位置:[6_1](/notes/Java核心技术卷一6_1.md) 193 | 194 | 195 | 196 | ### 内部类 197 | 198 | 章节:6.3 199 | 200 | 笔记位置:[6_2](/notes/Java核心技术卷一6_2.md) 201 | 202 | 203 | 204 | ## UPD 205 | 206 | 2019.06.04 开始阅读并做笔记 207 | 208 | 2019.06.19 创建 git 仓库进行维护 209 | 210 | 2019.06.24 开启第 6 章,开始总结重点内容 211 | 212 | 2019.06.25 开启第 7 章,增加目录部分 213 | 214 | 2019.06.26 第 7 章中 7.5 日志部分内容暂缺,开启第 8 章 215 | 216 | 2019.07.05 开启第 9 章 -------------------------------------------------------------------------------- /notes/Java核心技术卷一7_2.md: -------------------------------------------------------------------------------- 1 | # 《Java核心技术卷一》 笔记 7_2 2 | 3 | 2019.06.26 15:19 4 | 5 | 6 | 7 | ## 第7章 异常、断言和日志 8 | 9 | ### 7.4 使用断言 10 | 11 | 在一个具有自我保护能力的程序中,断言很常用 12 | 13 | 14 | 15 | #### 7.4.1 断言的概念 16 | 17 | 假设确信某个属性符合要求,并且代码的执行依赖于这个属性,此时可以使用断言。 18 | 19 | 当然可以使用抛出异常的方式 20 | 21 | ```java 22 | if(x < 0) throw new IllegalArgumentException("x < 0"); 23 | ``` 24 | 25 | 但是抛出异常会一直留在程序里,即使测试完毕也不会自动删除,如果包含了大量的这样类型的检查,程序效率就会受到影响。 26 | 27 | 断言机制允许测试期间向代码中插入一些检查语句,当代码发布时,插入的检测语句将会被自动的移走。 28 | 29 | Java 语言引入了关键字 assert 有两种使用形式 30 | 31 | ```java 32 | assert 条件; 33 | assert 条件 : 表达式; 34 | ``` 35 | 36 | 两种形式都会对条件进行判断,如果是 false,就抛出一个 AssertionError 异常 37 | 38 | 对于第二种形式表达式将会被传入 AssertionError 构造器转化成消息字符串 39 | 40 | 41 | 42 | C 中 assert 会用宏把条件打印出来,Java 如果需要条件,需要自己增加字符串 43 | 44 | 45 | 46 | #### 7.4.2 启用和禁用断言 47 | 48 | 默认情况下断言被禁用 49 | 50 | 可以在运行程序时 51 | 52 | ```shell 53 | java -enableassertions MyApp 54 | java -ea MyApp 55 | ``` 56 | 57 | 两种任意一个启用断言 58 | 59 | 启用和禁用断言不需要重新编译,因为这是类加载器(class loader)的功能 60 | 61 | 当断言被禁用时,类加载器会跳过断言代码,因此不会降低程序运行效率 62 | 63 | 64 | 65 | 也可以对某个类或某个包使用断言 66 | 67 | ```shell 68 | java -ea:com.mycompany.mylib -ea:MyClass MyApp 69 | ``` 70 | 71 | 或者禁用某些断言 72 | 73 | ```shell 74 | java -da:MyClass MyApp 75 | java -disableassertions MyApp 76 | ``` 77 | 78 | 79 | 80 | 有些类不是由类加载器加载的,而是由虚拟机直接加载的,对于这些类,使用 81 | 82 | -enablesystemassertions 或者 -esa 来开启 83 | 84 | 85 | 86 | #### 7.4.3 使用断言完成参数检查 87 | 88 | 断言失败是致命的、不可恢复的错误 89 | 90 | 断言检查只用于开发和测试阶段 91 | 92 | 不应该使用断言向应用其他部分通告发生了可恢复错误 93 | 94 | 不应该使用断言作为通告用户的手段 95 | 96 | 97 | 98 | 可以看如 sort 的文档 99 | 100 | ```java 101 | /** 102 | ... 103 | @param a the array to be sorted 104 | @throws IllegalArgumentException if fromIndex > toIndex 105 | */ 106 | static void sort(int[] a, int fromIndex, int toIndex) 107 | ``` 108 | 109 | 这里如果下标错误就该抛出错误而不是使用断言判断 110 | 111 | 对于 a 是否为 null 112 | 113 | 由于文档没有规定行为,那么 a 数组完全可以为 null 并正确运行返回 114 | 115 | 如果文档改为 116 | 117 | ```java 118 | /** 119 | ... 120 | @param a the array to be sorted (must not be null) 121 | @throws IllegalArgumentException if fromIndex > toIndex 122 | */ 123 | ``` 124 | 125 | 此时应该使用断言判断 a 不为 null 126 | 127 | 计算机科学家称这种约定为前置条件(precondition) 128 | 129 | 修订 a 不为 null 后方法有了一个前置条件 130 | 131 | 132 | 133 | #### 7.4.4 为文档假设使用断言 134 | 135 | 很多程序员使用注释来说明假设条件,其实使用断言更好 136 | 137 | ```java 138 | if(i % 3 == 0) { 139 | 140 | } else if(i % 3 == 1) { 141 | 142 | } else { // i % 3 == 2 143 | 144 | } 145 | ``` 146 | 147 | 使用断言的版本 148 | 149 | ```java 150 | if(i % 3 == 0) { 151 | 152 | } else if(i % 3 == 1) { 153 | 154 | } else { 155 | assert i % 3 == 2; 156 | 157 | } 158 | ``` 159 | 160 | 实际上 i 可能是负值 161 | 162 | 163 | 164 | ClassLoaderAPI.java 165 | 166 | ```java 167 | public class ClassLoaderAPI { 168 | public static void main(String[] args) { 169 | // java.lang.ClassLoader 170 | // void setDefaultAssertionStatus(boolean b) 171 | 172 | // void setClassAssertionStatus(String className, boolean b) 173 | 174 | // void setPackageAssertionStatus(String packageName, boolean b) 175 | 176 | // void clearAssertionStatus 177 | // 移除所有类和包的显示断言状态 178 | } 179 | } 180 | ``` 181 | 182 | 183 | 184 | ## 7.5 记录日志 185 | 186 | 日志记录是一种在程序整个生命周期都可以使用的策略性工具 187 | 188 | 日志 API 就是为了解决调试时需要不断反复插入和删除输出语句的问题。 189 | 190 | 191 | 192 | 日志 API 的优点: 193 | 194 | 可以很容易的取消全部日志记录,或仅仅取消某个个级别的日志 195 | 196 | 可以简单的禁止日志记录的输出,将日志代码留在程序中开销很小 197 | 198 | 日志记录可以被定向到不同的处理器,在控制台显示或存储到文件 199 | 200 | 日志记录器和处理器都可以对记录进行过滤。过滤器可以丢弃无用的记录项 201 | 202 | 日志记录可以采用不同的方式格式化 203 | 204 | 应用程序可以使用多个日志记录器,它们使用类似包名的具有层次结构的名字 205 | 206 | 默认情况下,日志系统的配置由配置文件控制,应用程序可以替换这个配置 207 | 208 | 209 | 210 | #### 7.5.1 基本日志 211 | 212 | 生成简单日志可以使用全局日志记录器(global logger) 213 | 214 | ```java 215 | Logger.getGlobal().info("File->Open menu item selected"); 216 | ``` 217 | 218 | 适当位置调用 219 | 220 | ```java 221 | Logger.getGlobal().setLevel(Level.OFF); 222 | ``` 223 | 224 | 会取消所有日志 225 | 226 | 227 | 228 | #### 7.5.2 高级日志 229 | 230 | 企业级(industrial-strength)日志 231 | 232 | 专业的应用不要将所有的日志记录到一个全局的日志记录器中,而是应当自定义日志记录器 233 | 234 | ```java 235 | private static final Logger myLogger = Logger.getLogger("com.mycompany.myapp"); 236 | ``` 237 | 238 | 未被任何变量引用的日志记录器可能会被垃圾回收,应当用静态变量储存日志记录器的引用 239 | 240 | 241 | 242 | 日志记录器具有层次结构,且父子之间共享部分属性,子记录器会继承父记录器的日志级别 243 | 244 | 通常有 7 个日志级别: 245 | 246 | SEVERE 247 | 248 | WARNING 249 | 250 | INFO 251 | 252 | CONFIG 253 | 254 | FINE 255 | 256 | FINER 257 | 258 | FINEST 259 | 260 | 默认只记录前三个级别 261 | 262 | 可以使用 Level.ALL 开启所有级别记录,也可以使用 Level.OFF 关闭所有级别记录 263 | 264 | 可以使用 265 | 266 | ```java 267 | logger.warning(message); 268 | logger.fine(message); 269 | logger.log(Level.FINE, message); 270 | ``` 271 | 272 | 273 | 274 | 默认的日志记录将显示日志调用的类和方法名,但是虚拟机可能对执行过程进行了优化,不能得到准确位置,此时可以使用 logp 方法 275 | 276 | ```java 277 | void logp(Level l,String className, String methodName, String message); 278 | ``` 279 | 280 | 281 | 282 | 一些跟踪执行流的方法 283 | 284 | ```java 285 | void entering(String className, String methodName); 286 | void entering(String className, String methodName, Object param); 287 | void entering(String className, String methodName, Object[] params); 288 | void exiting(String className, String methodName); 289 | void exiting(String className, String methodName, Object result); 290 | ``` 291 | 292 | 会生成 FINER 级别 ENTRY 或 RETURN 开始的日志记录 293 | 294 | 295 | 296 | 日志通常是为了记录那些不可预料的异常 297 | 298 | 可以用以下方法提供日志记录中包含的异常描述信息 299 | 300 | ```java 301 | void throwing(String className, String methodName, Throwable t); 302 | void log(Level l, String message, Throwable t); 303 | ``` 304 | 305 | throwing 将记录 THROW 开始的 FINE 级别的记录 306 | 307 | 308 | 309 | #### 7.5.3 修改日志管理器配置 310 | 311 | (暂缺) -------------------------------------------------------------------------------- /notes/Java核心技术卷一9_0.md: -------------------------------------------------------------------------------- 1 | # 《Java核心技术卷一》 笔记 9_0 2 | 3 | 2019.07.08 09:28 4 | 5 | 6 | 7 | ## 第9章 集合 8 | 9 | ### 9.1 Java 集合框架 10 | 11 | Java 最初只提供了很少的类: Vector、Stack、HashTable、BitSet 和 Enumeration 12 | 13 | Java SE 1.2 开始推出了新的集合框架 14 | 15 | 16 | 17 | #### 9.1.1 将集合的接口与实现分离 18 | 19 | Java 集合类库也将接口(interface)和实现(implementation)分离 20 | 21 | 例如 Queue 的最简形式可能如下 22 | 23 | ```java 24 | public interface Queue { 25 | void add(E element); 26 | E remove(); 27 | int size(); 28 | } 29 | ``` 30 | 31 | 这并没有指定实现队列的方式 32 | 33 | 队列通常有如下两种实现 34 | 35 | 使用循环数组 36 | 37 | ```java 38 | public class CircularArrayQueue implements Queue { 39 | private int head; 40 | private int tail; 41 | private E[] elements; 42 | 43 | CircularArrayQueue(int capacity){...} 44 | public void add(E element){...} 45 | public E remove(){...} 46 | public int size(){...} 47 | } 48 | ``` 49 | 50 | 使用链表 51 | 52 | ```java 53 | public class LinkedListQueue implements Queue { 54 | private Link head; 55 | private Link tail; 56 | 57 | LinkedListQueue(){...} 58 | public void add(E element){...} 59 | public E remove(){...} 60 | public int size(){...} 61 | } 62 | ``` 63 | 64 | 65 | 66 | 实际 Java 类库中提供类似功能的类是 ArrayDeque 和 LinkedList 67 | 68 | 69 | 70 | 一旦创建集合就不需要知道具体使用了哪种实现,因此可以使用接口类型存放集合引用 71 | 72 | ```java 73 | Queue expressLane = new CircularArrayQueue<>(100); 74 | expressLane.add(new Customer("Harry")); 75 | ``` 76 | 77 | 78 | 79 | 这样实际更改实现时,只需要在定义处更改即可 80 | 81 | ```java 82 | Queue expressLane = new LinkedListQueue<>(); 83 | ``` 84 | 85 | 86 | 87 | 因为接口只决定了行为,而具体实现决定了效率,有时有了更好效率的实现,就可以使用这种简单的更改方式。 88 | 89 | 90 | 91 | Java 中会有一组 Abstract 开头的类,实现自己的类时,扩展 Abstract 类比自己实现对应的接口要容易。 92 | 93 | 94 | 95 | #### 9.1.2 Collection 接口 96 | 97 | 集合类的基本接口是 Collection 接口 98 | 99 | 这个接口有两个基本方法 100 | 101 | ```java 102 | public interface Collection { 103 | boolean add(E element); 104 | // 向集合添加元素,如果集合变化返回 true 否则返回 false 105 | Iterator iterator(); 106 | // iterator 方法返回一个实现了 Iterator 接口的对象,能够依次遍历集合中的对象 107 | ... 108 | } 109 | ``` 110 | 111 | 112 | 113 | #### 9.1.3 迭代器 114 | 115 | Iterator 116 | 117 | ```java 118 | public interface Iterator { 119 | E next(); 120 | boolean hasNext(); 121 | void remove(); 122 | default void forEachRemaining(Consumer action); 123 | } 124 | ``` 125 | 126 | 通过调用 hasNext 判断是否还有下个元素,使用 next 来得到下个元素。如果已经达到集合末尾调用 next 则会抛出 NoSuchElementException,因此调用 next 前应当使用 hasNext 检查 127 | 128 | ```java 129 | Collection c = ...; 130 | Iterator iter = c.iterator(); 131 | while(iter.hasNext()) { 132 | String element = iter.next(); 133 | ... 134 | } 135 | ``` 136 | 137 | 也可以使用 for each 简化这个过程 138 | 139 | ```java 140 | for(String element : c) { 141 | ... 142 | } 143 | ``` 144 | 145 | for each 可以与任何实现了 Iterable 接口的对象一起工作 146 | 147 | ```java 148 | public interface Iterable { 149 | Iterator iterator(); 150 | } 151 | ``` 152 | 153 | 154 | 155 | Collection 接口也扩展了 Iterable 接口,因此标准类库中的所有集合都可以使用 for each 156 | 157 | 158 | 159 | Java SE 8 中甚至不需要写循环,可以调用 forEachRemaining 方法 并提供一个 lambda 表达式 160 | 161 | ```java 162 | iterator.forEachRemaining(element -> ...); 163 | ``` 164 | 165 | 166 | 167 | 元素访问的顺序取决于集合的类型,但可以保证不重不漏的遍历所有元素 168 | 169 | 170 | 171 | Iterable 接口的 next 和 hasNext 与 Enumeration 接口的 nextElement 与 hasMoreElements 的作用一样,但要更简洁。 172 | 173 | 174 | 175 | Java 集合类库的迭代器与其他类库中的迭代器概念上有重要区别。传统集合类库迭代器根据数组索引建模,给定一个迭代器就可以查看指定位置上的元素,不需要查找元素就可以移动迭代器位置。 176 | 177 | Java 的迭代器查找操作和位置变更是紧密相连的。查找元素的唯一方法时 next 而与此同时迭代器位置会移动。因此,Java 迭代器被认为是在两个元素之间,当调用 next 时,越过一个元素,并且返回越过的元素的引用。 178 | 179 | 可以将 Iterator.next 与 InputStream.read 视作等效 180 | 181 | 182 | 183 | Iterator 接口中的 remove 方法会删除上次调用 next 方法越过的元素 184 | 185 | ```java 186 | Iterator it = c.iterator(); 187 | it.next(); 188 | it.remove(); 189 | ``` 190 | 191 | 如果调用 remove 之前没有调用 next 将抛出 IllegalStateException 异常 192 | 193 | 如果想删除两个相邻的元素必须先删除一个越过一个再删除另一个 194 | 195 | ```java 196 | it.remove(); 197 | it.next(); 198 | it.remove(); 199 | ``` 200 | 201 | 202 | 203 | #### 9.1.4 泛型实用方法 204 | 205 | ```java 206 | public static boolean contains(Collection c, Object obj) { 207 | for(E element : c) 208 | if(element.equals(obj)) return true; 209 | return false; 210 | } 211 | ``` 212 | 213 | 实际 Collection 接口声明了很多向上面的实用方法 214 | 215 | ```java 216 | int size() 217 | boolean isEmpty() 218 | boolean contains(Object obj) 219 | boolean containsAll(Collection c) 220 | boolean equals(Object other) 221 | boolean addAll(Collection from) 222 | boolean remove(Object obj) 223 | boolean removeAll(Collection c) 224 | void clear() 225 | boolean retainAll(Collection c) 226 | Object[] toArray() 227 | T[] toArray(T[] arrayToFill) 228 | default boolean removeIf(Predicate filter) 229 | // 删除 filter 返回 true 的所有元素 230 | ``` 231 | 232 | 233 | 234 | #### 9.1.5 集合框架中的接口 235 | 236 | ```text 237 | Iterable 238 | ^ 239 | | 240 | Collection Map Iterator RandomAccess 241 | ^ ^ ^ 242 | | | | 243 | ---------- --------- | | 244 | | | | | | 245 | List Set Queue SortedMap ListIterator 246 | ^ ^ ^ 247 | | | | 248 | SortedSet Deque | 249 | ^ | 250 | | NavigableMap 251 | NavigableSet 252 | ``` 253 | 254 | 255 | 256 | 集合有来能个基本接口 Collection 和 Map 257 | 258 | 259 | 260 | ##### Map 261 | 262 | Map 是键值对因此使用 put 方法插入元素 263 | 264 | ```java 265 | V put(K key, V value) 266 | ``` 267 | 268 | 读取则使用 get 方法 269 | 270 | ```java 271 | V get(K key) 272 | ``` 273 | 274 | 275 | 276 | ##### List 277 | 278 | List 是一个有序集合,元素会增加到容器特定位置,可以使用迭代器或数组索引访问 279 | 280 | 也可以使用数组下标进行随机访问(random access) 281 | 282 | 用于随机访问的方法 283 | 284 | ```java 285 | void add(int index, E element) 286 | void remove(int index) 287 | E get(int index) 288 | E set(int index, E element) 289 | ``` 290 | 291 | ListIterator 接口是 Iterator 的子接口,定义类一个在迭代器前面增加元素的方法 292 | 293 | ```java 294 | void add(E element) 295 | ``` 296 | 297 | 298 | 299 | Java SE 1.4 引入了一个标记接口 RandomAccess 300 | 301 | 这个接口中没有任何方法,用来判断是否支持高效随机访问 302 | 303 | ```java 304 | if(c instanceof RandomAccess) { 305 | use random access algorithm 306 | } else { 307 | use sequential access algorithm 308 | } 309 | ``` 310 | 311 | 312 | 313 | ##### Set 314 | 315 | Set 接口等同于 Collection 接口,不过对方法的行为有更严谨的定义。 316 | 317 | add 方法不允许添加重复元素 318 | 319 | equals 方法只考虑包含的所有元素是否一致,而不考虑顺序 320 | 321 | hashCode 方法保证元素相同的两个集合得到的散列码一致 322 | 323 | 324 | 325 | SortedSet 和 SortedMap 提供了用于排序的比较器,定义了可以得到集合子集视图的方法 326 | 327 | 328 | 329 | NavigableSet 和 NavigableMap 包含了用于搜索和遍历有序集和映射的方法 330 | 331 | TreeSet 和 TreeMap 实现了这些方法 332 | 333 | 334 | 335 | -------------------------------------------------------------------------------- /notes/Java核心技术卷一4_0.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 《Java核心技术卷一》 笔记 4_0 4 | 5 | 2019.06.14 12:11 6 | 7 | 8 | 9 | ## 第4章 对象与类 10 | 11 | ### 4.1 面向对象程序设计(OOP)概述 12 | 13 | #### 4.1.1 类 14 | 15 | 类(class)是构造对象的模板或蓝图 16 | 17 | 由类构建(construct)对象的过程称为创建类的实例(instance) 18 | 19 | 封装(encapsulation,有时称为数据隐藏)形式上,封装将数据和行为组合在一个包中,并对对象的使用者隐藏了数据的实现方式。 20 | 21 | 实例域(Instance field)对象中的数据 22 | 23 | 方法(Method)操纵数据的过程 24 | 25 | 状态(state)对于某个特定类对象的一组特定的实例域值的组合,就是当前对象的状态 26 | 27 | 封装赋予类黑盒特性 28 | 29 | 继承(Inheritance)通过一个类来创建另一个类的过程 30 | 31 | 32 | 33 | #### 4.1.2 对象 34 | 35 | 对象 3 个主要特性: 36 | 37 | 对象的行为(behavior)可对对象施加的方法 38 | 39 | 对象的状态(state)对象对于方法的响应如何 40 | 41 | 对象的标识(identity)判别具有相同行为和状态的不同对象的唯一标识 42 | 43 | 44 | 45 | 对象状态变化必须通过调用方法,不然就破坏了封装性 46 | 47 | 48 | 49 | #### 4.1.3 识别类 50 | 51 | OOP 从设计类开始,再向类中添加方法 52 | 53 | 识别类可以分析问题过程中的名词,方法则对应动词 54 | 55 | 56 | 57 | #### 4.1.4 类之间的关系 58 | 59 | 类之间的常见关系有 60 | 61 | 依赖(Dependence,uses-a)一个类的方法操纵另一个类的对象,则一个类依赖于另一个类 62 | 63 | 应当减少依赖(耦合度最小) 64 | 65 | 聚合(Aggregation,has-a)一种对象包含一些另一种对象 66 | 67 | 继承(Inheritance,is-a)特殊与一般的类之间的关系 68 | 69 | 70 | 71 | 有一系列表示类关系的 UML(Unified Modeling Language) 符号 72 | 73 | 74 | 75 | ### 4.2 使用预定义类 76 | 77 | 并不是所有类都有面向对象特性 78 | 79 | 80 | 81 | #### 4.2.1 对象与对象变量 82 | 83 | 使用构造器(constructor)来构建新实例。构造器是一种特殊的方法构建和初始化对象。 84 | 85 | 构造器名字与类名相同 86 | 87 | 88 | 89 | 对象与对象变量不同 90 | 91 | 一个对象变量并没有真正包含对象,而是一个对象的引用 92 | 93 | 设置对象变量为 null 表示没有引用任何对象 94 | 95 | 96 | 97 | Java 的引用更像安全版的 C++ 指针 98 | 99 | 100 | 101 | #### 4.2.2 Java 类库中的 LocalDate 类 102 | 103 | Date 类实例的状态就是特定的时间点,保存从特定时间,纪元(epoch)开始的毫秒数 104 | 105 | 纪元是 UTC/GMT 1970.01.01 00:00:00 106 | 107 | 108 | 109 | Java 将保存时间点和给时间点命名分成了两个类。 110 | 111 | 保存时间点使用 Date 类 112 | 113 | 保存日历表示法,给时间点命名的是 LocalDate 类 114 | 115 | 116 | 117 | 使用 LocalDate 类不使用构造器,要用静态工厂方法(factory method) 118 | 119 | DateAndLocalDate.java 120 | 121 | ```java 122 | import java.util.*; // Date 123 | import java.time.*; // LocalDate 124 | 125 | public class DateAndLocalDate { 126 | public static void main(String[] args) { 127 | Date birthday = new Date(); 128 | System.out.println("Date : " + birthday); 129 | 130 | LocalDate nowLocalDate = LocalDate.now(); 131 | LocalDate oldLocalDate = LocalDate.of(1966,1,1); 132 | System.out.println("nowLocalDate : " + nowLocalDate); 133 | System.out.println("oldLocalDate : " + oldLocalDate); 134 | 135 | System.out.println("now year : " + nowLocalDate.getYear()); 136 | System.out.println("now month : " + nowLocalDate.getMonth()); 137 | System.out.println("now month value : " + nowLocalDate.getMonthValue()); 138 | System.out.println("now day of month : " + nowLocalDate.getDayOfMonth()); 139 | System.out.println("now day of year : " + nowLocalDate.getDayOfYear()); 140 | } 141 | } 142 | ``` 143 | 144 | 不要使用 Date 中的 getYear 等方法,已经过时 145 | 146 | 147 | 148 | #### 4.2.3 更改器方法与访问器方法 149 | 150 | 更改器方法(mutator method)修改对象的方法 151 | 152 | 访问器方法(accessor method)不修改对象的方法 153 | 154 | 155 | 156 | C++ 中默认是更改器方法,后加 const 关键字为访问器方法 157 | 158 | Java 不做语法区分 159 | 160 | CalendarTest.java 161 | 162 | ```java 163 | import java.time.*; 164 | public class CalendarTest { 165 | public static void main(String[] args) { 166 | LocalDate date = LocalDate.now(); 167 | int month = date.getMonthValue(); 168 | int today = date.getDayOfMonth(); 169 | 170 | date = date.minusDays(today - 1); 171 | DayOfWeek weekday = date.getDayOfWeek; 172 | int value = weekday.getValue(); 173 | 174 | System.out.println("Mon Tue Wed Thu Fri Sat Sun"); 175 | for(int i = 1; i < value; i++) 176 | System.out.print(" "); 177 | 178 | while(date.getMonthValue() == month) 179 | { 180 | System.out.printf("%3d", date.getDayOfMonth()); 181 | if(date.getDayOfMonth() == today) 182 | System.out.print("*"); 183 | else 184 | System.out.print(" "); 185 | date = date.plusDays(1); 186 | if(date.getDayOfWeek().getValue() == 1) 187 | System.out.println(); 188 | } 189 | if(date.getDayOfWeek().getValue() != 1) 190 | System.out.println(); 191 | } 192 | } 193 | ``` 194 | 195 | 196 | 197 | ### 4.3 用户自定义类 198 | 199 | 复杂应用程序需要各种主力类(workhorse class)这些类通常没有 main 方法,只有自己的实例域和实例方法。 200 | 201 | 一个完整的应用程序有若干类,只有其中一个类有 main 方法 202 | 203 | 204 | 205 | #### 4.3.1 Employee 类 206 | 207 | Java 中最简单的类定义 208 | 209 | ```java 210 | class ClassName { 211 | 212 | 213 | ... 214 | 215 | 216 | ... 217 | 218 | 219 | ... 220 | } 221 | ``` 222 | 223 | EmployeeTest.java 224 | 225 | ```java 226 | import java.time.*; 227 | 228 | public class EmployeeTest 229 | { 230 | public static void main(String[] args) { 231 | Employee[] staff = new Employee[3]; 232 | 233 | staff[0] = new Employee("Carl Cracker", 75000, 1987, 12, 15); 234 | staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1); 235 | staff[2] = new Employee("Tony Tester", 40000, 1990, 3, 15); 236 | 237 | for(Employee e : staff) 238 | e.raiseSalary(5); 239 | 240 | for(Employee e : staff) 241 | System.out.println("name=" + e.getName() + ", salary=" + e.getSalary() 242 | + ", hireDay=" + e.getHireDay()); 243 | } 244 | } 245 | 246 | class Employee { 247 | private String name; 248 | private double salary; 249 | private LocalDate hireDay; 250 | public Employee(String n, double s, int year, int month, int day) { 251 | name = n; 252 | salary = s; 253 | hireDay = LocalDate.of(year, month, day); 254 | } 255 | public String getName() { 256 | return name; 257 | } 258 | public double getSalary() { 259 | return salary; 260 | } 261 | public LocalDate getHireDay() { 262 | return hireDay; 263 | } 264 | public void raiseSalary(double byPercent) { 265 | double raise = salary * byPercent / 100; 266 | salary += raise; 267 | } 268 | } 269 | ``` 270 | 271 | 272 | 273 | #### 4.3.2 多个源文件的使用 274 | 275 | 可以认为 Java 内置了 make 工具。 276 | 277 | 如将 EmployeeTest 类和 Employee 分别放置于两个文件下,则可以使用两种方式进行编译。 278 | 279 | 第一种使用通配符,第二种可以直接使用命令 280 | 281 | ```shell 282 | javac EmployeeTest.java 283 | ``` 284 | 285 | 当编译发现需要 Employee 类时会自动寻找这个类并比较 .java 和 .class 的版本 286 | 287 | 如果不存在 .class 或者 .java 比已有的 .class 更新 则重新编译成 .class 288 | 289 | 290 | 291 | #### 4.3.3 剖析 Employee 类 292 | 293 | public 意味着所有类都可以访问 294 | 295 | private 意味着只有所属的类内部有访问权限 296 | 297 | 298 | 299 | #### 4.3.4 从构造器开始 300 | 301 | 构造器与类同名 302 | 303 | 可以有多个构造器 304 | 305 | 构造器的参数个数可以是任意的 306 | 307 | 构造器没有返回值 308 | 309 | 构造器总是伴随 new 操作一起调用 310 | 311 | 312 | 313 | Java 中对象都是在堆中构建需要注意。 314 | 315 | 不要在构造器中定义与实例域重名的局部变量 316 | 317 | 318 | 319 | #### 4.3.5 隐式参数与显式参数 320 | 321 | 隐式(implicit)参数:调用函数的对象 322 | 323 | 显示(explicit)参数:参数表中声明的 324 | 325 | 每个方法中关键字 this 代表了隐式参数,必要时可以用 this 强调是实例域中的变量 326 | 327 | 328 | 329 | C++ 通常在类外定义函数,类内定义的会被默认内联 330 | 331 | Java 只能在类内定义方法,内联由虚拟机决定 332 | 333 | 334 | 335 | #### 4.3.6 封装的优点 336 | 337 | 可以保证内部一些变量是只读的 338 | 339 | 需要获得或者设置实例域值的情况可以设置以下 3 个部分: 340 | 341 | 一个私有的数据域,一个共有的域访问器方法,一个共有的域更改器方法 342 | 343 | 可以在改变内部实现的情况下不影响其他外部的代码。 344 | 345 | 可以在更改时对更改内容进行检查 346 | 347 | 348 | 349 | 不要编写返回饮用可变对象的访问器方法,这样在更改引用的对象的时候就会破坏封装性 350 | 351 | 对于可变对象可以用 clone 返回对象的副本的引用 352 | 353 | ```java 354 | return (Date) day.clone(); 355 | ``` 356 | 357 | 358 | 359 | #### 4.3.7 基于类的访问权限 360 | 361 | 一个方法可以访问所属类的所有对象的私有特性,而不只是隐式参数的私有特性 362 | 363 | 364 | 365 | #### 4.3.8 私有方法 366 | 367 | 应将所有的数据域设置为私有 368 | 369 | 对于方法,辅助方法最好私有 370 | 371 | 372 | 373 | 一般私有方法在内部实现改变不在需要时可以删除,共有的方法则不能随意删除 374 | 375 | 376 | 377 | #### 4.3.9 final 实例域 378 | 379 | 定义成 final 的实例域在对象构建时必须初始化,并在之后的操作中不能更改。 380 | 381 | final 大多用在基本类型(primitive)域或不可变(immutable)类的域 382 | 383 | 不可变类:类中的每个方法都不会改变其对象 384 | 385 | 386 | 387 | 对于可变类,final 只是意味着引用的引用对象不能改变为引用其他对象,但是引用对象的内容可以改变 388 | 389 | -------------------------------------------------------------------------------- /notes/Java核心技术卷一4_2.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 《Java核心技术卷一》 笔记 4_2 4 | 5 | 2019.06.19 12:08 6 | 7 | 8 | 9 | ## 第4章 对象与类 10 | 11 | ### 4.7 包 12 | 13 | Java 使用包将类组织起来,方便分开管理不同的代码库 14 | 15 | 所有的标准 java 包在 java 和 javax 包层次结构中 16 | 17 | 18 | 19 | 使用包的原因是为确保类名的唯一性。同名的类放于不同的包下就可以避免冲突 20 | 21 | 22 | 23 | 建议使用域名反写作为唯一的包名,不同项目使用子包 24 | 25 | 26 | 27 | 从编译器的角度嵌套的包之间没有关系。例如 java.util 包与 java.util.jar 包没有关系 28 | 29 | 30 | 31 | #### 4.7.1 类的导入 32 | 33 | 可以使用带包名的完整类名 34 | 35 | ```java 36 | java.time.LocalDate today = java.time.LocalDate.now(); 37 | ``` 38 | 39 | 可以使用如下语句直接导入 java.time 中的所有类(没有副作用) 40 | 41 | ```java 42 | import java.time.*; 43 | ``` 44 | 45 | 这样使用时可以直接 46 | 47 | ```java 48 | LocalDate today = LocalDate.now(); 49 | ``` 50 | 51 | 或者可以使用 52 | 53 | ```java 54 | import java.time.LocalDate; 55 | ``` 56 | 57 | 直接导入特定类 58 | 59 | 60 | 61 | 如果两个包有命名冲突时可以特别增加冲突的名字从哪个包中导入 62 | 63 | ```java 64 | import java.util.*; 65 | import java.sql.*; 66 | import java.util.Date; 67 | ``` 68 | 69 | 如果两个类都要用到就必须用完整类名的形式了 70 | 71 | 72 | 73 | ##### import 与 C++ include 74 | 75 | import 的行为与 C++ include 的行为是不同的。 76 | 77 | C++ 编译器不能查看 当前编译文件及头文件中包含的文件 以外的文件, 78 | 79 | Java 编译器可以查看其他文件内部,只需给出去哪查看即可 80 | 81 | Java 可以总是写完整类名而不写 import 而 C++ 无法避免 import 82 | 83 | 84 | 85 | C++ 与 包机制类似的是 namespace 和 using 声明 86 | 87 | 88 | 89 | #### 4.7.2 静态导入 90 | 91 | import 可以导入静态方法或者静态域 92 | 93 | ```java 94 | import static java.lang.System.*; 95 | ``` 96 | 97 | 之后可以使用‘ 98 | 99 | ```java 100 | out.println("Hi"); 101 | exit(0); 102 | ``` 103 | 104 | 也可以使用 105 | 106 | ```java 107 | import static java.lang.System.out; 108 | ``` 109 | 110 | 111 | 112 | #### 4.7.3 将类放入包中 113 | 114 | ```java 115 | package com.horstmann.corejava; 116 | 117 | import ... 118 | 119 | public class ClassName { 120 | 121 | } 122 | ``` 123 | 124 | 将类放入包中的基本格式如上 125 | 126 | 127 | 128 | 没有 package 的包会被放入默认包(default package)中 129 | 130 | 默认包是一个没有名字的包 131 | 132 | 133 | 134 | 包中的文件应当放于与完整包名匹配的子目录下 如 com.horstmann.corejava 包应当放于 135 | 136 | com/horstmann/corejava 目录下 137 | 138 | ```text 139 | -root 140 | | 141 | --- PackageTest.java 142 | --- PackageTest.class 143 | | 144 | --- com/ 145 | | 146 | --- horstmann/ 147 | | 148 | --- corejava/ 149 | | 150 | --- Employee.java 151 | --- Employee.class 152 | ``` 153 | 154 | 编译并运行 155 | 156 | ```shell 157 | javac PackageTest.java 158 | java PackageTest 159 | ``` 160 | 161 | 162 | 163 | 更复杂的情况 164 | 165 | ```text 166 | -root 167 | | 168 | --- com/ 169 | | 170 | --- horstmann/ 171 | | | 172 | | --- corejava/ 173 | | | 174 | | --- Employee.java 175 | | --- Employee.class 176 | | 177 | --- mycompany/ 178 | | 179 | --- PayrollApp.java 180 | --- PayrollApp.class 181 | ``` 182 | 183 | 此时要在根目录完成编译和运行 184 | 185 | ```shell 186 | javac com/mycompany/PayrollApp.java 187 | java com/mycompany/PayrollApp 188 | ``` 189 | 190 | 191 | 192 | 编译器在编译源文件的时候不检查目录结构 193 | 194 | 如果包与目录不匹配最终虚拟机不能找到类 195 | 196 | 197 | 198 | 需要设置环境变量 CLASSPATH 的值为 199 | 200 | ```java 201 | .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar 202 | ``` 203 | 204 | 没有第一个 .; 可能不会到当前目录下寻找包 205 | 206 | 文件目录 207 | 208 | ```text 209 | root 210 | | 211 | --- PackageTest.java 212 | | 213 | --- com/ 214 | | 215 | --- mypackage/ 216 | | 217 | --- Employee.java 218 | ``` 219 | 220 | PackageTest.java 221 | 222 | ```java 223 | import com.mypackage.*; 224 | import static java.lang.System.*; 225 | 226 | public class PackageTest { 227 | public static void main(String[] args) { 228 | Employee harry = new Employee("Harry Hacker", 50000, 1989, 10, 1); 229 | 230 | harry.raiseSalary(5); 231 | 232 | out.println("name = " + harry.getName() + ", salary = " + harry.getSalary()); 233 | } 234 | } 235 | ``` 236 | 237 | Employee.java 238 | 239 | ```java 240 | package com.mypackage; 241 | 242 | import java.time.*; 243 | 244 | public class Employee { 245 | private String name; 246 | private double salary; 247 | private LocalDate hireDay; 248 | public Employee(String n, double s, int year, int month, int day) { 249 | name = n; 250 | salary = s; 251 | hireDay = LocalDate.of(year, month, day); 252 | } 253 | public String getName() { 254 | return name; 255 | } 256 | public double getSalary() { 257 | return salary; 258 | } 259 | public LocalDate getHireDay() { 260 | return hireDay; 261 | } 262 | public void raiseSalary(double byPercent) { 263 | double raise = salary * byPercent / 100; 264 | salary += raise; 265 | } 266 | } 267 | ``` 268 | 269 | 270 | 271 | #### 4.7.4 包作用域 272 | 273 | 没有指定 private 和 public 的方法或域,可以被同一包内方法访问 274 | 275 | 包不是一个封闭的实体,可以人为向包中添加方法,因此应该尽量让包中的变量是 private 的 276 | 277 | 278 | 279 | JDK 1.2 之后类加载器禁止加载用户自定义的 java. 开头的包 280 | 281 | 282 | 283 | 更好的手段是通过包密封(package sealing)机制解决各种包混杂的问题 284 | 285 | 密封的包不能再添加类,见第 9 章 286 | 287 | 288 | 289 | ### 4.8 类路径 290 | 291 | 类可以存储在文件系统子目录中。类路径需要与包名匹配 292 | 293 | 类也可以存储在 JAR (Java 归档)中 294 | 295 | 296 | 297 | 环境变量 CLASSPATH 用来设置寻找类和 jar 包的位置 298 | 299 | 可以在寻找 jar 的目录使用通配符 300 | 301 | 302 | 303 | 如果匹配了一个以上的类,就会返回错误 304 | 305 | 306 | 307 | #### 4.8.1 设置类路径 308 | 309 | ```shell 310 | java -classpath c:\classdir;.;c:\archives\archive.jar MyProg 311 | ``` 312 | 313 | 或者在命令行(Linux) 314 | 315 | ```shell 316 | export CLASSPATH= 317 | ``` 318 | 319 | (Windows) 320 | 321 | ```shell 322 | set CLASSPATH= 323 | ``` 324 | 325 | 将在退出 shell 之前都有效 326 | 327 | 328 | 329 | ### 4.9 文档注释 330 | 331 | JDK 包含一个由源文件生成 HTML 文档的工具 javadoc 332 | 333 | 334 | 335 | #### 4.9.1 注释的插入 336 | 337 | javadoc 实体应用(utility)将从下面几个特性抽取信息 338 | 339 | 包 340 | 341 | 公有类与接口 342 | 343 | 公有的和受保护的构造器及方法 344 | 345 | 公有的和受保护的域 346 | 347 | 348 | 349 | 注释应当放于所描述的特性前并以 350 | 351 | ```java 352 | /** 353 | ``` 354 | 355 | 开始,并以 356 | 357 | ```java 358 | */ 359 | ``` 360 | 361 | 结束 362 | 363 | 文档注释在标记之后紧跟自由格式文本(free-form text)。标记由 @ 开始 364 | 365 | 如 @author @param 366 | 367 | 自由格式文本第一句应该是概要性的句子,将用来生成概要页。 368 | 369 | 370 | 371 | 可以使用 HTML 372 | 373 | 374 | 375 | #### 4.9.2 类注释 376 | 377 | 类注释放在 import 之后 类定义之前 378 | 379 | 大多数 IDE 会在每行补充 * 开头 不过这不是必须的 380 | 381 | 382 | 383 | #### 4.9.3 方法注释 384 | 385 | 放在方法前,可以使用 386 | 387 | @param 变量 描述,方法所有变量描述要放在一起 388 | 389 | @return 描述 390 | 391 | @throws 异常类描述 392 | 393 | 394 | 395 | #### 4.9.4 域注释 396 | 397 | 通常只对公有域(静态常量)建立文档 398 | 399 | 400 | 401 | #### 4.9.5 通用注释 402 | 403 | @author 作者,可以有多个 404 | 405 | @version 文本 406 | 407 | @since 文本 408 | 409 | @deprecated 文本,过时写法不再使用,可以通过@see 或 @link 跳转到其他新的方法描述 410 | 411 | @see 引用 引用部分的格式是 类名#方法,或者在当前类时直接给出方法 412 | 413 | 也可以使用超链接 414 | 415 | @link 可以在任意位置增加链接,用法同 @see 416 | 417 | 418 | 419 | #### 4.9.6 包与描述注释 420 | 421 | 包注释需要在单独的文件提供 422 | 423 | package.html 424 | 425 | 或者一个 426 | 427 | package-info.java 的文件 428 | 429 | 该文件只应该包含 package 语句和 /\*\* \*/ 注释部分 430 | 431 | 432 | 433 | 可以对所有源文件提供注释在 overview.html 下 434 | 435 | 436 | 437 | #### 4.9.7 注释的提取 438 | 439 | 假设 html 放于 doc 目录下 440 | 441 | 切换到想生成文档的源文件目录 442 | 443 | 444 | 445 | 如果是一个包,执行 446 | 447 | ```shell 448 | javadoc -d doc nameOfPackage 449 | ``` 450 | 451 | 多个包 452 | 453 | ```shell 454 | javadoc -d doc package1 package2 ... 455 | ``` 456 | 457 | 文件在默认包中则 458 | 459 | ```shell 460 | javadoc -d doc *.java 461 | ``` 462 | 463 | 不建议省略 -d doc 不然 html 会生成在当前文件夹下 464 | 465 | 466 | 467 | 还有一些其他的 javadoc 命令可用 468 | 469 | 470 | 471 | ### 4.10 类设计技巧 472 | 473 | 1 保证数据私有 474 | 475 | 2 要对数据初始化 476 | 477 | 3 不要在类中使用过多的基本类型(用其他类代替) 478 | 479 | 4 不是所有域都需要独立的访问器和更改器 480 | 481 | 5 将职责过多的类分解 482 | 483 | 6 类名和方法名能够体现职责 484 | 485 | ​ 采用名词或形容词修饰的名词,动名词修饰的名词,访问器 get 开头,修改器 set 开头 486 | 487 | 7 优先使用不可变类 488 | 489 | ​ 类是可变的,多线程会发生并发更改,从而线程不安全 -------------------------------------------------------------------------------- /notes/Java核心技术卷一8_1.md: -------------------------------------------------------------------------------- 1 | # 《Java核心技术卷一》 笔记 8_1 2 | 3 | 2019.06.27 11:38 4 | 5 | 6 | 7 | ## 第8章 泛型程序设计 8 | 9 | ### 8.6 约束与局限性 10 | 11 | Java 泛型使用时有一些局限性,多数局限性是由类型擦除引起的 12 | 13 | 14 | 15 | #### 8.6.1 不能用基本类型实例化类型参数 16 | 17 | 因为类型擦除后为 Object 或者其子类,因此无法存储基本类型 18 | 19 | 20 | 21 | #### 8.6.2 运行时类型查询只适用于原始类型 22 | 23 | 注意 24 | 25 | ```java 26 | if(a instanceof Pair) 27 | if(a instanceof Pair) 28 | ``` 29 | 30 | 以上写法不能通过编译 31 | 32 | 而 33 | 34 | ```java 35 | Pair p = (Pair) a; 36 | ``` 37 | 38 | 会得到警告 39 | 40 | 41 | 42 | getClass 将总会返回对应的原始类型 43 | 44 | ```java 45 | Pair strPair = ...; 46 | Pair empPair = ...; 47 | if(strPair.getClass() == empPair.getClass()) // true 48 | ``` 49 | 50 | 51 | 52 | #### 8.6.3 不能创建参数化类型的数组 53 | 54 | 不能使用如下写法 55 | 56 | ```java 57 | Pair[] table = new Pair[10]; 58 | ``` 59 | 60 | 但是可以声明 61 | 62 | ```java 63 | Pair[] table; 64 | ``` 65 | 66 | 可以使用通配类型 67 | 68 | ```java 69 | Pair[] table = (Pair) new Pair[10]; 70 | ``` 71 | 72 | 但这并不安全 73 | 74 | 应当使用 75 | 76 | ```java 77 | ArrayList> 78 | ``` 79 | 80 | 81 | 82 | #### 8.6.4 Varargs 警告 83 | 84 | ```java 85 | public static void addAll(Collection coll, T... ts) { 86 | for(T t : ts) coll.add(t); 87 | } 88 | ``` 89 | 90 | 考虑如下调用 91 | 92 | ```java 93 | Collection> table = ...; 94 | Pair p1 = ...; 95 | Pair p2 = ...; 96 | addAll(table, p1, p2); 97 | ``` 98 | 99 | 这种情况会得到警告而不是错误 100 | 101 | 可以使用 102 | 103 | ```java 104 | @SuppressWarning("unchecked") 105 | ``` 106 | 107 | 或者 Java SE 7 后 108 | 109 | ```java 110 | @SafeVarages 111 | ``` 112 | 113 | 直接标注方法 114 | 115 | 116 | 117 | 可以依靠这个特性创造泛型数组 118 | 119 | ```java 120 | @SafeVarages 121 | static E[] array(E... array) { 122 | return array; 123 | } 124 | ``` 125 | 126 | 但是可以将错误类型的对象引用赋值给数组某个元素,而不会报错 127 | 128 | 直到使用时才会报错 129 | 130 | 131 | 132 | #### 8.6.5 不能实例化类型变量 133 | 134 | 不能使用 new T(…),new T[…] 或 T.class 135 | 136 | 因为类型擦除会将 T 转化为 Object,而这并不是操作的本意 137 | 138 | Java SE 8 之后可以使用 139 | 140 | ```java 141 | Pair p = Pair.makePair(String::new); 142 | ``` 143 | 144 | makePair 方法定义如下 145 | 146 | ```java 147 | public static Pair makePair(Supplier constr) { 148 | return new Pair<>(constr.get(), constr.get()); 149 | } 150 | ``` 151 | 152 | 153 | 154 | 比较传统的方法如下 155 | 156 | ```java 157 | public static Pair makePair(Class cl) { 158 | try { 159 | return new Pair<>(cl.newInstance(), cl.newInstance()); 160 | } catch (Exception ex) { 161 | return null; 162 | } 163 | } 164 | ``` 165 | 166 | 使用以下方式调用 167 | 168 | ```java 169 | Pair p = Pair.makePair(String.class); 170 | ``` 171 | 172 | Class 类本身是泛型的,String.class 是 Class\ 的唯一实例 173 | 174 | 175 | 176 | #### 8.6.6 不能构造泛型数组 177 | 178 | 这和不能实例化对象一致,因为类型会被擦除 179 | 180 | 此时可以提供一个数组构造器表达式 181 | 182 | ```java 183 | String[] ss = ArrayAlg.minmax(String[]::new, "Tom", "Dick", "Harry"); 184 | ``` 185 | 186 | 部分定义如下 187 | 188 | ```java 189 | public static T[] minmax(IntFunction constr, T... a) { 190 | T[] mm = constr.apply(2); 191 | ... 192 | } 193 | ``` 194 | 195 | 196 | 197 | 比较老式的方法是使用反射 198 | 199 | ```java 200 | public static T[] minmax(T... a) { 201 | T[] mm = (T[]) Array.newInstance(a.getClass().getComponentType(), 2); 202 | ... 203 | } 204 | ``` 205 | 206 | 207 | 208 | ArrayList 的 toArray 方法有两个版本 209 | 210 | ```java 211 | Object[] toArray(); 212 | T[] toArray(T[] result); 213 | ``` 214 | 215 | 对于第二个版本如果 result 数组够大,就是用 result 数组,否则根据 result 类型创建一个新的 216 | 217 | 218 | 219 | #### 8.6.7 泛型类的静态上下文中类型变量无效 220 | 221 | 不能在静态域或方法中引用类型变量。因为类型擦除后只有一个静态域,因此不能使用类型变量 222 | 223 | 224 | 225 | #### 8.6.8 不能抛出或捕获泛型类的实例 226 | 227 | 不能抛出或捕获泛型类的对象,甚至泛型类扩展 Throwable 都是不合法的 228 | 229 | 230 | 231 | 不过可以在异常规范中使用类型变量 232 | 233 | ```java 234 | public static void doWork(T t) throws T { 235 | try { 236 | do work 237 | } catch (Throwable realCause) { 238 | t.init(realCause); 239 | throw t; 240 | } 241 | } 242 | ``` 243 | 244 | 245 | 246 | #### 8.6.9 可以消除对受查异常的检查 247 | 248 | 可以使用泛型消除受查异常必须提供处理器的限制 249 | 250 | ```java 251 | @SuppressWarnings("unchecked") 252 | public static void throwAs(Throwable e) throws T { 253 | throw (T) e; 254 | } 255 | ``` 256 | 257 | 假设上述代码在类 Block 中 258 | 259 | ```java 260 | try { 261 | do work 262 | } catch (Throwable t) { 263 | Block.throwAs(t); 264 | } 265 | ``` 266 | 267 | 这样会把所有异常转换为非受查异常 268 | 269 | 270 | 271 | ErasedCheckedTest.java 272 | 273 | ```java 274 | import java.util.*; 275 | import java.io.*; 276 | 277 | public class ErasedCheckedTest { 278 | public static void main(String[] args) { 279 | new Block() { 280 | public void body() throws Exception { 281 | Scanner in = new Scanner(new File("ququx"), "UTF-8"); 282 | while(in.hasNext()) 283 | System.out.println(in); 284 | } 285 | }.toThread().start(); 286 | } 287 | } 288 | 289 | abstract class Block { 290 | public abstract void body() throws Exception; 291 | public Thread toThread() { 292 | return new Thread() { 293 | public void run() { 294 | try { 295 | body(); 296 | } catch (Throwable t) { 297 | Block.throwAs(t); 298 | } 299 | } 300 | }; 301 | } 302 | @SuppressWarnings("unchecked") 303 | public static void throwAs(Throwable e) throws T { 304 | throw (T) e; 305 | } 306 | } 307 | ``` 308 | 309 | 结果 310 | 311 | ```text 312 | Exception in thread "Thread-0" java.io.FileNotFoundException: ququx (系统找不到指定的 313 | 文件。) 314 | at java.io.FileInputStream.open0(Native Method) 315 | at java.io.FileInputStream.open(Unknown Source) 316 | at java.io.FileInputStream.(Unknown Source) 317 | at java.util.Scanner.(Unknown Source) 318 | at java.util.Scanner.(Unknown Source) 319 | at ErasedCheckedTest$1.body(ErasedCheckedTest.java:8) 320 | at Block$1.run(ErasedCheckedTest.java:22) 321 | ``` 322 | 323 | 虽然报出了错误,但是 run 方法并不需要提供处理受查异常的操作 324 | 325 | 326 | 327 | #### 8.6.10 注意擦除后的冲突 328 | 329 | 当泛型擦除时,可能因为完全一样的条件引发冲突。 330 | 331 | 如擦除后形成一对方法名,参数,返回类型完全一致的函数,此时需要重命名冲突方法。 332 | 333 | 334 | 335 | 一个类或类型变量不能同时成为两个接口类型的子类,而两个接口是同一个接口的不同参数化 336 | 337 | 如,以下代码非法 338 | 339 | ```java 340 | class Employee implememts Comparable {...} 341 | class Manager extends Employee implememts Comparable {...} 342 | ``` 343 | 344 | 这与桥方法有关 345 | 346 | 对于不同的 Comparable\ 桥方法不能有两个? 347 | 348 | ```java 349 | public int comparaTo(Object other) { 350 | return compareTo((X) other); 351 | } 352 | ``` 353 | 354 | 355 | 356 | 不过非泛型的版本是可以的 357 | 358 | ```java 359 | class Employee implememts Comparable {...} 360 | class Manager extends Employee implememts Comparable {...} 361 | ``` 362 | 363 | 364 | 365 | ### 8.7 泛型类型的继承规则 366 | 367 | 无论 S 与 T 之间是什么关系,通常 Pair\ 与 Pair\ 没有关系 368 | 369 | 所以即使 S 是 T 的子类,Pair\ 与 Pair\ 之间是不能赋值的 370 | 371 | 注意这一点泛型与数组的行为不同,但数组在赋值时带有特殊保护,这是泛型不具备的 372 | 373 | 374 | 375 | 永远可以将参数化类型转化为原始类型 376 | 377 | 378 | 379 | 泛型类可以扩展或实现其他泛型类 380 | 381 | 382 | 383 | ```text 384 | ---------------> <> <-------------------- 385 | | List | 386 | | ^ | 387 | <> . <> 388 | List . List 389 | ^ . ^ 390 | . . . 391 | . ---------------> ArrayList <------------------ . 392 | . | (raw) | . 393 | . | | . 394 | ArrayList - - - no relationship - - - - - ArrayList 395 | ``` 396 | 397 | \-\.\-\.\-\. implements 398 | 399 | \-\-\-\-\-\- extends 400 | 401 | \- \- \- no relationship -------------------------------------------------------------------------------- /notes/Java核心技术卷一8_2.md: -------------------------------------------------------------------------------- 1 | # 《Java核心技术卷一》 笔记 8_2 2 | 3 | 2019.06.27 15:31 4 | 5 | 6 | 7 | ## 第8章 泛型程序设计 8 | 9 | ### 8.8 通配符类型 10 | 11 | 固定的泛型类型使用起来有些限制,于是有了统配符类型 12 | 13 | 14 | 15 | #### 8.8.1 通配符概念 16 | 17 | 通配符类型中,允许类型参数变化。通配符类型 18 | 19 | ```java 20 | Pair 21 | ``` 22 | 23 | 比如针对下面的函数 24 | 25 | ```java 26 | public static void printBuddies(Pair p) { 27 | Employee first = p.getFirst(); 28 | Employee second = p.getSecond(); 29 | System.out.println(first.getName() + " and " + second.getName() + " are buddies."); 30 | } 31 | ``` 32 | 33 | 就不能传递参数 Pair\ 34 | 35 | 此时应该使用通配符类型 36 | 37 | ```java 38 | public static void printBuddies(Pair p) { 39 | Employee first = p.getFirst(); 40 | Employee second = p.getSecond(); 41 | System.out.println(first.getName() + " and " + second.getName() + " are buddies."); 42 | } 43 | ``` 44 | 45 | 类型之间的关系 46 | 47 | ```text 48 | Pair 49 | (raw) 50 | ^ 51 | | 52 | Pair 53 | ^ ^ 54 | | | 55 | Pair Pair 56 | ``` 57 | 58 | 59 | 60 | 通配符类型的引用 61 | 62 | ```java 63 | Pair managerBuddies = new Pair<>(ceo,cfo); 64 | Pair wcBuddies = managerBuddies; 65 | // wcBuddies.setFirst(lowlyEmployee); 66 | ``` 67 | 68 | 这样调用 set 方法不会通过编译 69 | 70 | 因为 set 方法看起来如下 71 | 72 | ```java 73 | //void setFirst(? extends Employee) 74 | ``` 75 | 76 | 编译器并不知道实际传递的是什么类型,这将拒绝所有的特定类型 77 | 78 | get 方法则可以正常使用。 79 | 80 | ```java 81 | Employee e = wcBuddies.getFirst(); 82 | ``` 83 | 84 | 因为传递出来的总会是 Employee 的子类对象 85 | 86 | 87 | 88 | #### 8.8.2 通配符的超类型限定 89 | 90 | 通配符限定于类型变量限定很像,但还可以使用超类型限定(supertype bound) 91 | 92 | 统配符限制为某个类的所有超类 93 | 94 | ```java 95 | Pair 96 | // void setFirst(? super Manager) 97 | // ? super Manager getFirst() 98 | ``` 99 | 100 | 此时将不能使用 get 方法,因为只知道得到的结果可以赋值给 Object 101 | 102 | 使用 set 方法则是安全的,此时传递的对象不能是 Employee 或者 Object,只能传递 Manager 或其子类型对象 103 | 104 | 105 | 106 | 例子 107 | 108 | ```java 109 | public static void minmaxBonus(Manager[] a, Pair result) { 110 | if(a.length == 0) return; 111 | Manager min = a[0]; 112 | Manager max = a[0]; 113 | for(int i = 1; i < n; i++) { 114 | if(min.getBonus() > a[i].getBonus()) min = a[i]; 115 | if(max.getBonus() < a[i].getBonus()) max = a[i]; 116 | } 117 | result.setFirst(min); 118 | result.setSecond(max); 119 | } 120 | ``` 121 | 122 | 如上 result 可以由 Manager 及其超类构建的 Pair 123 | 124 | 125 | 126 | 对于实现了泛型接口的情况 127 | 128 | ```java 129 | public interface Comparable { 130 | public int compareTo(T other); 131 | } 132 | class ArrayAlg 133 | { 134 | public static > T min(T[] a) { 135 | 136 | } 137 | } 138 | ``` 139 | 140 | 可以在 extends 后面的接口也使用泛型 141 | 142 | 143 | 144 | 但是继承可能会和这样的泛型设定冲突 145 | 146 | 比如,LocalDate 实现了 ChronoLocalDate 而 ChronoLocalDate 扩展了 Comparable\ 而不是 Comparable\ 147 | 148 | 此时就要 149 | 150 | ```java 151 | public static > T min(T[] a) 152 | ``` 153 | 154 | 可能实现了 T 或 T 超类的的 Comparable 此时传入 T 或其子类参数是安全的 155 | 156 | 157 | 158 | 超类限定可能用于函数式接口 159 | 160 | ```java 161 | default boolean removeIf(Predicate filter) 162 | ``` 163 | 164 | 希望传入 Object 而不仅是 Employee 的时候就可以使用这种方式 165 | 166 | 167 | 168 | #### 8.8.3 无限定通配符 169 | 170 | ```java 171 | Pair 172 | // ? getFirst() 173 | // void setFirst(?) 174 | ``` 175 | 176 | 注意 getFirst 只能赋值给 Object 177 | 178 | setFirst 方法则不能使用包括 Object 在内的对象调用 179 | 180 | 只可以 181 | 182 | ```java 183 | setFirst(null); 184 | ``` 185 | 186 | 可以写出一个判空方法 187 | 188 | ```java 189 | public static boolean hasNull(Pair p) { 190 | return p.getFirst() == null || p.getSecond() == null; 191 | } 192 | ``` 193 | 194 | 当然也可以只使用泛型 195 | 196 | ```java 197 | public static boolean hasNull(Pair p) 198 | ``` 199 | 200 | 201 | 202 | #### 8.8.4 通配符捕获 203 | 204 | 注意统配符不是类型变量,因此不能书写如下代码 205 | 206 | ```java 207 | public static void swap(Pair p) { 208 | // ? t = p.getFirst(); 209 | } 210 | ``` 211 | 212 | 不过可以通过辅助方法 213 | 214 | ```java 215 | public static void swapHelper(Pair p) { 216 | T t = p.getFirst(); 217 | p.setFirst(p.getSecond()); 218 | p.setSecond(t); 219 | } 220 | public static void swap(Pair p) { 221 | swapHelper(p); 222 | } 223 | ``` 224 | 225 | 此时参数 T 将会捕获通配符 226 | 227 | 228 | 229 | 有些时候需要使用通配符捕获 230 | 231 | ```java 232 | public static void maxminBonus(Manager[] a, Pair result) { 233 | minmaxBonus(a, result); 234 | PairAlg.swap(result); 235 | } 236 | ``` 237 | 238 | 其中 swap 函数就需要类型是 Pair\ 239 | 240 | 241 | 242 | 编译器必须确信通配符表达的是单个、确定的类型时,捕获才是合法的。 243 | 244 | 245 | 246 | PairTest3.java 247 | 248 | ```java 249 | import java.time.*; 250 | 251 | public class PairTest3 { 252 | public static void main(String[] args) { 253 | Manager ceo = new Manager("Gus Greedy", 800000, 2003, 12, 15); 254 | Manager cfo = new Manager("Sid Sneaky", 600000, 2003, 12, 15); 255 | Pair buddies = new Pair<>(ceo,cfo); 256 | printBuddies(buddies); 257 | ceo.setBonus(1000000); 258 | cfo.setBonus(500000); 259 | 260 | Manager[] managers = {ceo, cfo}; 261 | Pair result = new Pair<>(); 262 | minmaxBonus(managers, result); 263 | printBuddies(result); 264 | maxminBonus(managers, result); 265 | printBuddies(result); 266 | } 267 | 268 | public static void printBuddies(Pair p) { 269 | Employee first = p.getFirst(); 270 | Employee second = p.getSecond(); 271 | System.out.println(first.getName() + " and " + second.getName() + " are buddies."); 272 | } 273 | public static void minmaxBonus(Manager[] a, Pair result) { 274 | if(a.length == 0) return; 275 | Manager min = a[0]; 276 | Manager max = a[0]; 277 | for(int i = 1; i < a.length; i++) { 278 | if(min.getBonus() > a[i].getBonus()) min = a[i]; 279 | if(max.getBonus() < a[i].getBonus()) max = a[i]; 280 | } 281 | result.setFirst(min); 282 | result.setSecond(max); 283 | } 284 | public static void maxminBonus(Manager[] a, Pair result) { 285 | minmaxBonus(a,result); 286 | //PairAlg.swap(result); 287 | PairAlg.swapHelper(result); 288 | } 289 | } 290 | 291 | class Pair { 292 | private T first; 293 | private T second; 294 | public Pair() { first = null; second = null; } 295 | public Pair(T first, T second) { 296 | this.first = first; 297 | this.second = second; 298 | } 299 | public T getFirst() { return first; } 300 | public T getSecond() { return second; } 301 | public void setFirst(T newValue) { first = newValue; } 302 | public void setSecond(T newValue) { second = newValue; } 303 | } 304 | 305 | class PairAlg { 306 | public static boolean hasNulls(Pair p) { 307 | return p.getFirst() == null || p.getSecond() == null; 308 | } 309 | public static void swap(Pair p) { 310 | swapHelper(p); 311 | } 312 | public static void swapHelper(Pair p) { 313 | T t = p.getFirst(); 314 | p.setFirst(p.getSecond()); 315 | p.setSecond(t); 316 | } 317 | } 318 | 319 | class Employee { 320 | private String name; 321 | private double salary; 322 | private LocalDate hireDay; 323 | public Employee(String n, double s, int year, int month, int day) { 324 | name = n; 325 | salary = s; 326 | hireDay = LocalDate.of(year, month, day); 327 | } 328 | public String getName() { 329 | return name; 330 | } 331 | public double getSalary() { 332 | return salary; 333 | } 334 | public LocalDate getHireDay() { 335 | return hireDay; 336 | } 337 | public void raiseSalary(double byPercent) { 338 | double raise = salary * byPercent / 100; 339 | salary += raise; 340 | } 341 | } 342 | class Manager extends Employee { 343 | private double bonus; 344 | 345 | public Manager(String name, double salary, int year, int month, int day) { 346 | super(name, salary, year, month, day); 347 | bonus = 0; 348 | } 349 | 350 | void setBonus(double bonus) { 351 | this.bonus = bonus; 352 | } 353 | 354 | public double getBonus() { 355 | return bonus; 356 | } 357 | 358 | public double getSalary() { 359 | return super.getSalary() + bonus; 360 | } 361 | } 362 | ``` 363 | 364 | 结果 365 | 366 | ```text 367 | Gus Greedy and Sid Sneaky are buddies. 368 | Sid Sneaky and Gus Greedy are buddies. 369 | Gus Greedy and Sid Sneaky are buddies. 370 | ``` -------------------------------------------------------------------------------- /notes/Java核心技术卷一8_3.md: -------------------------------------------------------------------------------- 1 | # 《Java核心技术卷一》 笔记 8_3 2 | 3 | 2019.07.05 15:40 4 | 5 | 6 | 7 | ## 第8章 泛型程序设计 8 | 9 | ### 8.9 反射和泛型 10 | 11 | 因为泛型运行时会被类型擦除,因此不会有太多的类型信息 12 | 13 | 反射也可以得到一些泛型类的信息 14 | 15 | 16 | 17 | #### 8.9.1 泛型 Class 类 18 | 19 | 现在的 Class 类也是泛型的,如 String.class 实际上是 Class\ 的唯一对象 20 | 21 | Class\ 中有一些方法使用了泛型 22 | 23 | ClassAPI.java 24 | 25 | ```java 26 | public class ClassAPI { 27 | public static void main(String[] args) { 28 | // java.lang.Class 29 | // T newInstance() 30 | // 用无参构造器构建一个新的 T 对象 31 | 32 | // T cast(Object obj) 33 | // obj 是 null 或可以转化成 T 的类型则返回 obj 34 | // 否则抛出 BadCastException 异常 35 | 36 | // T[] getEnumConstants() 37 | // 如果 T 是枚举类型(或是枚举值数组),返回所有值组成的数组 38 | 39 | // Class getSuperclass() 40 | // 返回这个类的超类。如果 T 不是一个类或是 Object 类则返回 null 41 | 42 | // Constructor getConstructor(Class... parameterTypes) 43 | // Constructor getDeclaredConstructor(Class... parameterTypes) 44 | // 获得给定参数类型的构造器 45 | } 46 | } 47 | ``` 48 | 49 | 50 | 51 | #### 8.9.2 使用 Class\ 参数进行类型匹配 52 | 53 | ```java 54 | public static Pair makePair(Class c) throws InstantiationException, 55 | IllegalAccessException { 56 | return new Pair<>(c.newInstance(), c.newInstance()); 57 | } 58 | ``` 59 | 60 | 可以通过以下语句 61 | 62 | ```java 63 | makePair(Employee.class) 64 | ``` 65 | 66 | 其中 Employee.class 是 Class\ 的对象,T 将匹配 Employee 于是可以得到 Pair\ 67 | 68 | 69 | 70 | #### 8.9.3 虚拟机中的泛型类型信息 71 | 72 | 对于泛型方法 73 | 74 | ```java 75 | public static > T min(T[] a) 76 | ``` 77 | 78 | 擦除类型后 79 | 80 | ```java 81 | public static Comparable min(Comparable[] a) 82 | ``` 83 | 84 | 可以使用反射 API 得到: 85 | 86 | 泛型方法有一个叫做 T 的类型参数 87 | 88 | 类型参数有一个子类型限定,其自身又是一个泛型类型,这个限定类型有一个通配符参数,通配符参数有一个超类限定 89 | 90 | 泛型方法有一个泛型数组参数 91 | 92 | 93 | 94 | 为了表达泛型类型声明,可以使用 java.lang.reflect 包中的 Type 95 | 96 | ```text 97 | <> <........ Class 98 | Type <---- --- <> TypeVariable 99 | | 100 | --- <> WildCardType 101 | | 102 | --- <> ParameterizedType 103 | | 104 | --- <> GenericArrayType 105 | ``` 106 | 107 | 108 | 109 | GenericReflectionTest.java 110 | 111 | ```java 112 | import java.lang.reflect.*; 113 | import java.util.*; 114 | 115 | public class GenericReflectionTest { 116 | public static void main(String[] args) { 117 | String name = "java.util.Collection"; 118 | try { 119 | Class cl = Class.forName(name); 120 | printClass(cl); 121 | for(Method m : cl.getDeclaredMethods()) { 122 | printMethod(m); 123 | } 124 | } catch (ClassNotFoundException e) { 125 | e.printStackTrace(); 126 | } 127 | } 128 | 129 | public static void printClass(Class cl) { 130 | System.out.print(cl); 131 | printTypes(cl.getTypeParameters(), "<", ", ", ">", true); 132 | Type sc = cl.getGenericSuperclass(); 133 | if(sc != null) { 134 | System.out.print(" extends "); 135 | printType(sc, false); 136 | } 137 | printTypes(cl.getGenericInterfaces(), " implements ", ", ", "", false); 138 | System.out.println(); 139 | } 140 | 141 | public static void printMethod(Method m) { 142 | String name = m.getName(); 143 | System.out.print(Modifier.toString(m.getModifiers())); 144 | System.out.print(" "); 145 | printTypes(m.getTypeParameters(), "<", ", ", "> ", false); 146 | 147 | printType(m.getGenericReturnType(), false); 148 | System.out.print(" " + name + "("); 149 | printTypes(m.getGenericParameterTypes(), "", ", ", "", false); 150 | System.out.println(")"); 151 | } 152 | 153 | public static void printTypes(Type[] types, String pre, String sep, String suf, boolean isDefinition) { 154 | if(pre.equals(" extends ") && Arrays.equals(types, new Type[]{ Object.class })) 155 | return; 156 | if(types.length > 0) System.out.print(pre); 157 | for(int i = 0; i < types.length; i++) { 158 | if(i > 0) System.out.print(sep); 159 | printType(types[i], isDefinition); 160 | } 161 | if(types.length > 0) System.out.print(suf); 162 | } 163 | 164 | public static void printType(Type type, boolean isDefinition) { 165 | if(type instanceof Class) { 166 | Class t = (Class) type; 167 | System.out.print(t.getName()); 168 | } else if (type instanceof TypeVariable) { 169 | TypeVariable t = (TypeVariable) type; 170 | System.out.print(t.getName()); 171 | if(isDefinition) 172 | printTypes(t.getBounds(), " extends ", " & ", "", false); 173 | } else if (type instanceof WildcardType) { 174 | WildcardType t = (WildcardType) type; 175 | System.out.print("?"); 176 | printTypes(t.getUpperBounds(), " extends ", " & ", "", false); 177 | printTypes(t.getLowerBounds(), " super ", " & ", "", false); 178 | } else if (type instanceof ParameterizedType) { 179 | ParameterizedType t = (ParameterizedType) type; 180 | Type owner = t.getOwnerType(); 181 | if(owner != null) { 182 | printType(owner, false); 183 | System.out.print("."); 184 | } 185 | printType(t.getRawType(), false); 186 | printTypes(t.getActualTypeArguments(), "<", ", ", ">", false); 187 | } else if (type instanceof GenericArrayType) { 188 | GenericArrayType t = (GenericArrayType) type; 189 | //System.out.print(" "); 190 | printType(t.getGenericComponentType(), isDefinition); 191 | System.out.print("[]"); 192 | } 193 | } 194 | } 195 | ``` 196 | 197 | 结果 198 | 199 | ```java 200 | interface java.util.Collection implements java.lang.Iterable 201 | public abstract boolean add(E) 202 | public abstract boolean remove(java.lang.Object) 203 | public abstract boolean equals(java.lang.Object) 204 | public abstract int hashCode() 205 | public abstract void clear() 206 | public abstract boolean contains(java.lang.Object) 207 | public abstract boolean isEmpty() 208 | public abstract java.util.Iterator iterator() 209 | public abstract int size() 210 | public abstract T[] toArray(T[]) 211 | public abstract [Ljava.lang.Object; toArray() 212 | public java.util.Spliterator spliterator() 213 | public abstract boolean addAll(java.util.Collection) 214 | public java.util.stream.Stream stream() 215 | public abstract boolean containsAll(java.util.Collection) 216 | public abstract boolean removeAll(java.util.Collection) 217 | public boolean removeIf(java.util.function.Predicate) 218 | public abstract boolean retainAll(java.util.Collection) 219 | public java.util.stream.Stream parallelStream() 220 | ``` 221 | 222 | 223 | 224 | GenericReflectionAPI.java 225 | 226 | ```java 227 | public class GenericReflectionAPI { 228 | public static void main(String[] args) { 229 | // java.lang.Class 230 | // TypeVariable[] getTypeParameters() 231 | // 如果类型是泛型类型 获得泛型类型变量,否则返回0长数组 232 | 233 | // Type getGenericSuperclass() 234 | // 返回泛型的超类类型,如果是 Object 或不是一个类类型(class type) 则返回 null 235 | 236 | // Type[] getGenericInterfaces() 237 | // 返回这个类型的接口的泛型类型,如果没有实现接口返回 0 长数组 238 | 239 | // java.lang.reflect.Method 240 | // TypeVarible[] getTypeParameters() 241 | // 方法的泛型类型变量,非泛型方法返回 0 长数组 242 | 243 | // Type getGenericReturnType() 244 | // 获得返回类型 245 | 246 | // Type[] getGenericParameterTypes() 247 | // 方法被声明的泛型参数类型,没有参数则返回 0 长数组 248 | 249 | // java.lang.reflect.TypeVariable 250 | // String getName() 251 | // 获得类型变量的名字 252 | 253 | // Type[] getBounds() 254 | // 获得类型变量的子类限定,无限定则返回 0 长数组 255 | 256 | // java.lang.reflect.WildcardType 257 | // Type[] getUpperBounds() 258 | // 得到子类限定 259 | 260 | // Type[] getLowerBounds() 261 | // 得到超类限定 262 | 263 | // java.lang.reflect.ParameterizedType 264 | // Type getRawType() 265 | // 获得参数化类型的原始类型 266 | 267 | // Type[] getActualTypeArguments() 268 | // 获得参数化类型声明时所使用的类型参数 269 | 270 | // Type getOwnerType() 271 | // 如果是内部类型,则返回其外部类型,顶级类型返回 null 272 | 273 | // java.lang.reflect.GenericArrayType 274 | // Type getGenericComponentType() 275 | // 获得声明该数组乐行的泛型组件类型 276 | } 277 | } 278 | ``` 279 | 280 | -------------------------------------------------------------------------------- /notes/Java核心技术卷一5_0.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 《Java核心技术卷一》 笔记 5_0 4 | 5 | 2019.06.19 16:50 6 | 7 | 8 | 9 | ## 第5章 继承(Inheritance) 10 | 11 | 本章介绍继承和反射(reflection)的概念 12 | 13 | 14 | 15 | ### 5.1 类、超类和子类 16 | 17 | 比如经理 Manager 也是员工 Employee 我们希望 Manager 可以直接使用 Employee 的一些属性和方法因此可以使用继承 18 | 19 | 20 | 21 | #### 5.1.1 定义子类 22 | 23 | ```java 24 | public class Manager extends Employee { 25 | 26 | } 27 | ``` 28 | 29 | 30 | 31 | Java 与 C++ 的继承方式类似 extends 关键字取代了 : 符号 32 | 33 | Java 所有继承都是公有继承没有私有和保护继承 34 | 35 | 36 | 37 | 已经存在的类称为 超类(superclass)、基类(base class)或者父类(parent class) 38 | 39 | 新派生出的类称为子类(subclass)、派生类(derived class)或孩子类(child class) 40 | 41 | 42 | 43 | 一般子类比超类功能更加丰富 44 | 45 | 子类会自动继承超类的域和方法而不必要显式定义 46 | 47 | 48 | 49 | #### 5.1.2 覆盖方法 50 | 51 | 超类有些方法子类并不适用,此时要提供一个新方法覆盖(Override)超类中的方法 52 | 53 | ```java 54 | public class Manager extends Employee { 55 | private double bonus; 56 | public double getSalary() { 57 | return salary + bonus; 58 | } 59 | } 60 | ``` 61 | 62 | 但此时并不能正常运行,因为子类的方法不能访问超类的私有域 63 | 64 | 此时需要使用 super 关键字调用超类方法 65 | 66 | ```java 67 | public class Manager extends Employee { 68 | private double bonus; 69 | public double getSalary() { 70 | return super.getSalary() + bonus; 71 | } 72 | } 73 | ``` 74 | 75 | 76 | 77 | 注意 super 和 this 的用法看起来相似,但其实是不同的概念 78 | 79 | super 并不是一个对象的引用,不能将 super 赋值给其他的变量 80 | 81 | 82 | 83 | 不能删除继承的超类的方法 84 | 85 | 86 | 87 | C++ 使用超类名和 :: 调用超类方法 88 | 89 | 90 | 91 | #### 5.1.3 子类构造器 92 | 93 | 可以使用 super 调用超类构造器 94 | 95 | 子类如果不显式调用超类的构造器,将会自动调用超类的无参构造器,没有定义时会出错 96 | 97 | 调用构造器的语句只能在构造器第一句出现 98 | 99 | 100 | 101 | ManagerTest.java 102 | 103 | ```java 104 | public class ManagerTest { 105 | public static void main(String[] args) { 106 | Manager boss = new Manager("Carl Cracker", 80000, 1987, 12, 15); 107 | boss.setBonus(5000); 108 | Employee[] staff = new Employee[3]; 109 | staff[0] = boss; 110 | staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1); 111 | staff[2] = new Employee("Tommy Tester", 40000, 1990, 3, 15); 112 | 113 | for(Employee e : staff) 114 | System.out.println("name = " + e.getName() + ", salary = " + e.getSalary()); 115 | 116 | } 117 | } 118 | ``` 119 | 120 | Manager.java 121 | 122 | ```java 123 | public class Manager extends Employee { 124 | private double bonus; 125 | 126 | public Manager(String name, double salary, int year, int month, int day) { 127 | super(name, salary, year, month, day); 128 | bonus = 0; 129 | } 130 | 131 | void setBonus(double bonus) { 132 | this.bonus = bonus; 133 | } 134 | 135 | public double getSalary() { 136 | return super.getSalary() + bonus; 137 | } 138 | } 139 | ``` 140 | 141 | Employee.java 142 | 143 | ```java 144 | import java.time.*; 145 | 146 | public class Employee { 147 | private String name; 148 | private double salary; 149 | private LocalDate hireDay; 150 | public Employee(String n, double s, int year, int month, int day) { 151 | name = n; 152 | salary = s; 153 | hireDay = LocalDate.of(year, month, day); 154 | } 155 | public String getName() { 156 | return name; 157 | } 158 | public double getSalary() { 159 | return salary; 160 | } 161 | public LocalDate getHireDay() { 162 | return hireDay; 163 | } 164 | public void raiseSalary(double byPercent) { 165 | double raise = salary * byPercent / 100; 166 | salary += raise; 167 | } 168 | } 169 | ``` 170 | 171 | 运行 172 | 173 | ```shell 174 | java ManagerTest 175 | ``` 176 | 177 | 得到结果 178 | 179 | ```text 180 | name = Carl Cracker, salary = 85000.0 181 | name = Harry Hacker, salary = 50000.0 182 | name = Tommy Tester, salary = 40000.0 183 | ``` 184 | 185 | 186 | 187 | 注意到 当把 boss 也视作 Employee 对象操作时依旧可以调用到自己的 getSalary() 188 | 189 | 多态(polymorphism)引用可以引用多种实际类型对象的现象 190 | 191 | 动态绑定(dynamic binding)运行时自动选择调用哪个方法 192 | 193 | 194 | 195 | Java 不需要将方法定义为 vitual,如果不需要虚拟特性可以标记为 final 196 | 197 | 198 | 199 | #### 5.1.4 200 | 201 | Java 继承不只限于一个层次。 202 | 203 | 继承层次(inheritance hierarchy)由一个公共超类派生出来的所有类的集合 204 | 205 | 继承链(inheritance chain)继承层次中,从某个特定的类到其祖先的路径 206 | 207 | 208 | 209 | Java 不同于 C++,不支持多重继承 210 | 211 | 212 | 213 | #### 5.1.5 多态 214 | 215 | 判断是否设计为继承,可以用 “is-a” 规则,即判断子类每个对象是不是也是超类的对象 216 | 217 | 另一种表述是置换法则,程序中任意位置的超类对象都可以用子类对象置换 218 | 219 | 220 | 221 | 超类对象变量任意时刻都可以引用子类对象(不需要强制类型转换) 222 | 223 | 不能将超类对象赋值给子类 224 | 225 | 226 | 227 | 子类数组引用可以赋值给超类数组的引用 228 | 229 | 但如果此时对超类数组的某个域进行赋值,赋值为超类对象 230 | 231 | 此时再调用子类数组该位置子类对象方法将会发生错误 232 | 233 | 234 | 235 | #### 5.1.6 理解方法调用 236 | 237 | 调用过程: 238 | 239 | 1.编译器查看对象的声明类型和方法名。编译器列举方法名所有同名方法和超类中 public 的同名方法 240 | 241 | 2.编译器查看调用方法时的参数类型,如果有一个完全匹配,则使用这个方法。这个过程称为重载解析(Overloading Resolution)。由于允许类型转换,所以这个过程很复杂。如果编译器没有找到参数类型匹配的方法,或类型转换后与多个方法匹配,则会报错 242 | 243 | 244 | 245 | 同样签名的子类方法会覆盖超类方法。返回类型不是签名的一部分,覆盖方法要保证返回类型的兼容性。 246 | 247 | ```java 248 | class Employee { 249 | public Employee f() {...} 250 | } 251 | class Manager extends Employee { 252 | public Manager f() {...} 253 | } 254 | ``` 255 | 256 | 如上,我们称两个f 具有可协变的返回类型。 257 | 258 | 259 | 260 | 3.对于 private,static,final 方法或构造器,由于能够准确知道调用哪个方法,我们称这种调用方式为静态绑定(static binding),与之对应的是需要依赖与隐式参数实际类型,运行时实现的动态绑定 261 | 262 | 263 | 264 | 4.当程序运行,并且采用动态绑定调用方法时,虚拟机调用实际类型最合适的类的方法。先从实际类型找方法,没用则找其超类。 265 | 266 | 为了不每次找方法都进行搜索,虚拟机创建了方法表(method table) 267 | 268 | 如果调用 super.f() 则编译器(应该是虚拟机?)将对隐式参数超类方法表进行搜索 269 | 270 | 271 | 272 | 动态绑定的重要特性:不需要对现存代码进行修改就可以对程序进行扩展。 273 | 274 | 275 | 276 | 覆盖方法时,子类方法不能低于超类方法的可见性。如果超类是 public 子类也必须是 public 277 | 278 | 279 | 280 | #### 5.1.7 组织继承:final 类和方法 281 | 282 | final 类:用 final 关键字修饰,不允许继承的类 283 | 284 | 类中方法也可以用 final 修饰,这样子类就不能覆盖这个方法。 285 | 286 | final 类中的方法会自动变成 final 方法(域不会变为 final) 287 | 288 | 289 | 290 | Java 默认具有多态性,而 C++ 默认没有 291 | 292 | 293 | 294 | 现在虚拟机可以通过推测,判断类的方法是否被覆盖。简短,频繁使用并且未被覆盖的方法将会被内联(inline),即使推断错误,也可以取消内联(过程慢,不过很少发生) 295 | 296 | 297 | 298 | #### 5.1.8 强制类型转换 299 | 300 | 如上将 Manager 对象存储在 Employee 数组后,如果需要使用 Manager 的方法,则需要强制类型转换 301 | 302 | ```java 303 | Manager b = (Manager)staff[0]; 304 | ``` 305 | 306 | 307 | 308 | 如果沿着继承链向下转化,但对象实际类型并不支持,会报 ClassCastException 异常 309 | 310 | 可以用 instanceof 判断 转换是否会成功 311 | 312 | ```java 313 | if(staff[1] instanceof Manager) 314 | b = (Manager)staff[1]; 315 | ``` 316 | 317 | 只能在继承层次内进行转换,超类转化为子类前要进行 instanceof 检查 318 | 319 | 一个没有引用对象的对象变量(null)使用 instanceof 总会得到 false 320 | 321 | 322 | 323 | 由于多态性,只有使用子类中的特有方法时才有类型转换的必要 324 | 325 | 326 | 327 | 强制类型转换类似于 C++ 的 dynamic_cast 328 | 329 | dynamic_cast 出错时会返回 NULL 而不是异常 330 | 331 | 332 | 333 | #### 5.1.9 抽象类 334 | 335 | 对于祖先类,可能某些高度抽象的方法无法提供具体实现,此时可以使用 abstract 将其定义为抽象函数,不需要给出实现。具体实现在子类中给出 336 | 337 | 有一个或多个抽象函数的类为抽象类 338 | 339 | ```java 340 | public abstract class Person { 341 | public abstract String getDescription(); 342 | } 343 | ``` 344 | 345 | 346 | 347 | 抽象类可以包含具体数据和具体方法。 348 | 349 | 350 | 351 | 抽象类可以不定义所有抽象方法派生出抽象类 352 | 353 | 也可以定义全部抽象方法从而变成具体类 354 | 355 | 356 | 357 | 类即使不含抽象方法,也可以定义为抽象类 358 | 359 | 抽象类不能实例化对象 360 | 361 | 可以创建具体的子类对象 362 | 363 | 可以创建抽象类的对象变量但只能引用具体子类的对象 364 | 365 | 366 | 367 | C++ 纯虚函数对应抽象函数概念,没有抽象类的关键字 368 | 369 | PersonTest.java 370 | 371 | ```java 372 | public class PersonTest { 373 | public static void main(String[] args) { 374 | Person[] people = new Person[2]; 375 | 376 | people[0] = new Employee("Harry Hacker", 50000, 1989, 10, 1); 377 | people[1] = new Student("Maria Morris", "computer science"); 378 | 379 | for(Person p : people) 380 | System.out.println(p.getName() + " : " + p.getDescription()); 381 | } 382 | } 383 | ``` 384 | 385 | Person.java 386 | 387 | ```java 388 | public abstract class Person { 389 | public abstract String getDescription(); 390 | 391 | private String name; 392 | 393 | public Person(String name) { 394 | this.name = name; 395 | } 396 | public String getName() { 397 | return name; 398 | } 399 | } 400 | ``` 401 | 402 | Employee.java 403 | 404 | ```java 405 | import java.time.*; 406 | 407 | public class Employee extends Person{ 408 | // private String name; 409 | private double salary; 410 | private LocalDate hireDay; 411 | public Employee(String name, double salary, int year, int month, int day) { 412 | super(name); 413 | this.salary = salary; 414 | hireDay = LocalDate.of(year, month, day); 415 | } 416 | // public String getName() { 417 | // return name; 418 | // } 419 | public double getSalary() { 420 | return salary; 421 | } 422 | public LocalDate getHireDay() { 423 | return hireDay; 424 | } 425 | public String getDescription() { 426 | return String.format("An employee with a salary of $%.2f", salary); 427 | } 428 | public void raiseSalary(double byPercent) { 429 | double raise = salary * byPercent / 100; 430 | salary += raise; 431 | } 432 | } 433 | ``` 434 | 435 | Student.java 436 | 437 | ```java 438 | public class Student extends Person { 439 | // private String name; 440 | private String major; 441 | public Student(String name, String major) { 442 | super(name); 443 | this.major = major; 444 | } 445 | public String getDescription() { 446 | return "A student majoring in " + major; 447 | } 448 | } 449 | ``` 450 | 451 | 结果 452 | 453 | ```text 454 | Harry Hacker : An employee with a salary of $50000.00 455 | Maria Morris : A student majoring in computer science 456 | ``` 457 | 458 | 459 | 460 | #### 5.1.10 受保护访问 461 | 462 | 希望子类可以访问超类的某些域或方法,可以将这些域或方法定义为 protected 463 | 464 | 尽量不要定义受保护域,不然可以通过派生来访问,破坏了封装性 465 | 466 | 467 | 468 | 实际上 Java 中 protected 除了子类 同一包中的其他类也都可见,这比 C++ 的 protected 安全性差 469 | 470 | 471 | 472 | private 仅对本类可见 473 | 474 | 默认 对本包可见 475 | 476 | protected 对子类和本包可见 477 | 478 | public 对所有类可见 --------------------------------------------------------------------------------