├── .gitignore ├── LICENSE ├── README.md ├── articles ├── .DS_Store ├── concurrent-action │ ├── share-combine.md │ └── thread-safety.md ├── effective-programming │ ├── class-interface.md │ ├── common-method.md │ ├── common-program-design.md │ ├── create-destory.md │ ├── current.md │ ├── enum-annotaion.md │ ├── exception.md │ ├── generic-paradigm2.md │ ├── method.md │ └── serialization.md ├── programming-thought │ ├── access-rights.md │ ├── array-container.md │ ├── concurrency.md │ ├── control-process.md │ ├── deep-container.md │ ├── enum-annotation.md │ ├── generic-paradigm.md │ ├── handle-exception.md │ ├── initial-and-clean.md │ ├── interface-innerclass.md │ ├── io.md │ ├── language-guide.md │ ├── object-ramble.md │ ├── operator.md │ ├── polymorphic.md │ ├── reuse-class.md │ ├── rtti-and-reflect.md │ └── string.md └── virtual-machine │ ├── gc-mas.md │ └── vmo-runtime.md ├── images ├── effective-programming │ ├── enum-annotaion │ │ └── run-tests.png │ ├── generic-paradigm2 │ │ ├── simple-stack-pop-all.png │ │ └── simple-stack-push-all.png │ └── method │ │ ├── assertion-error.png │ │ ├── configurations.png │ │ ├── period-test-2.png │ │ ├── period-test-3.png │ │ ├── period-test-4.png │ │ └── period-test.png ├── programming-thought │ ├── array-container │ │ ├── array-options.png │ │ ├── generic-and-upcasting.png │ │ └── test-container.png │ ├── control-process │ │ └── for-loop.png │ ├── deep-container │ │ ├── full-container-taxonomy.png │ │ └── simple-hash-map.png │ ├── generic-paradigm │ │ └── erased-type-equivalence.png │ ├── handle-exception │ │ ├── catch-a-exception.png │ │ ├── catch-a-new-exception.png │ │ ├── catch-simple-exception.png │ │ ├── declaration.png │ │ ├── initial-test-finally.png │ │ ├── runtime-exception.png │ │ ├── test-exception.png │ │ └── tips-exception.png │ ├── initial-and-clean │ │ ├── class-animal.png │ │ └── motto-hit.png │ ├── interface-innerclass │ │ ├── anonymous-inner-class2.png │ │ └── outer-inner-class.png │ ├── language-guide │ │ └── java-icon.png │ ├── operator │ │ ├── test-arithmetic.png │ │ ├── test-assignment.png │ │ ├── test-relation-2.png │ │ ├── test-relation-3.png │ │ └── test-relation.png │ ├── polymorphic │ │ ├── covariant-return-type.png │ │ ├── extends-system.png │ │ ├── global.png │ │ └── private-override.png │ ├── reuse-class │ │ └── class-a.png │ ├── rtti-and-reflect │ │ ├── compare-class.png │ │ ├── dot-class.png │ │ ├── load-class.png │ │ └── test-reflect.png │ └── string │ │ ├── hi-girl.png │ │ ├── javap-c-class.png │ │ ├── stack-over-flow-error.png │ │ ├── string-regular-expression.png │ │ └── test-reg.png └── virtual-machine │ └── vmo-runtime │ └── runtime-data-area.png └── javaskills ├── .gitignore ├── out └── production │ └── javaskills │ └── com │ └── hit │ └── thought │ ├── chapter1 │ └── LanguageGuide.md │ └── chapter16 │ ├── io │ ├── BasicFileOutput.out │ ├── Data.txt │ ├── FileOutputShortcut.out │ └── rtest.dat │ ├── nio │ └── data.txt │ ├── redirecting.out │ ├── textFileTest.txt │ └── textFileTest2.txt └── src └── com └── hit ├── concurrent ├── chapter1 │ ├── CachedFactorizer.java │ ├── CountingFactorizer.java │ ├── StatelessFactorizer.java │ ├── SynchronizedFactorizer.java │ ├── UnsafeCachingFactorizer.java │ ├── UnsafeCountingFactorizer.java │ ├── UnsafeSequence.java │ └── Widget.java ├── chapter2 │ ├── ImprovedList.java │ ├── NoVisibility.java │ └── PersonSet.java └── chapter3 │ └── HiddenIterate.java ├── effective ├── chapter1 │ ├── Finalizer.java │ ├── Foo.java │ ├── SimpleStack.java │ ├── StaticFactory.java │ ├── UtilityClass.java │ ├── init │ │ ├── NutritionFacts.java │ │ ├── NutritionFacts2.java │ │ └── NutritionFacts3.java │ ├── services │ │ ├── Provider.java │ │ ├── Service.java │ │ └── ServiceProviderFramework.java │ └── singleton │ │ ├── Elvis.java │ │ ├── Elvis2.java │ │ └── Elvis3.java ├── chapter10 │ └── StringList.java ├── chapter2 │ └── PhoneNumber.java ├── chapter3 │ ├── PhysicalConstants.java │ └── SecurityConstants.java ├── chapter4 │ └── SimpleStackPECS.java ├── chapter5 │ ├── annotation │ │ ├── ExceptionTest.java │ │ ├── MoreExceptionTest.java │ │ ├── RunExceptionTests.java │ │ ├── RunMoreExceptionTests.java │ │ ├── RunTests.java │ │ └── Test.java │ └── enums │ │ ├── IntEnum.java │ │ ├── Operation.java │ │ ├── Orange.java │ │ ├── PayrollDay.java │ │ └── Planet.java ├── chapter6 │ ├── CollectionClassifier.java │ ├── Period.java │ ├── UseAssertion.java │ └── VarargsMethod.java ├── chapter7 │ ├── ForEachCircle.java │ └── WhileCircle.java ├── chapter8 │ ├── CastException.java │ ├── HigherLevelException.java │ └── LowerLevelException.java └── chapter9 │ ├── DoubleCheckIdiom.java │ ├── HolderClassIdiom.java │ ├── SingleCheckIdiom.java │ ├── StopThread.java │ ├── StopThread2.java │ ├── StopThread3.java │ └── VolatileCase.java ├── thought ├── chapter1 │ └── LanguageGuide.md ├── chapter10 │ ├── FillException.java │ ├── FinallyException.java │ ├── MatchException.java │ ├── MyselfException.java │ ├── TestException.java │ └── TestRuntimException.java ├── chapter11 │ ├── ConnectionString.java │ ├── ObjectRegularExpression.java │ ├── RegularExpressionExample.java │ ├── StringRegularExpression.java │ └── UnconsciousRecursion.java ├── chapter12 │ ├── CheckClass.java │ ├── CompareClass.java │ ├── DotClass.java │ ├── Interface.java │ ├── LoadClass.java │ ├── NewInstance.java │ ├── RealObject.java │ ├── ShowMethods.java │ ├── SimpleDynamicProxy.java │ └── reflect │ │ ├── A.java │ │ ├── B.java │ │ ├── C.java │ │ └── TestReflect.java ├── chapter13 │ ├── ErasedTypeEquivalence.java │ ├── Fibonacci.java │ ├── Generator.java │ ├── GenericHolder.java │ ├── GenericMethod.java │ ├── GenericVarargs.java │ ├── LinkedStack.java │ ├── Manipulation.java │ └── SimpleHolder.java ├── chapter14 │ ├── ArrayOptions.java │ ├── ComparableImpl.java │ ├── ComparatorImpl.java │ ├── GenericAndUpcasting.java │ ├── MultidimensionalArray.java │ ├── ParameterizedArrayType.java │ ├── QueueDemo.java │ ├── SimpleIteration.java │ ├── Stack.java │ └── TestContainer.java ├── chapter15 │ ├── FullContainer.java │ ├── Groundhog.java │ ├── Groundhot2.java │ ├── Prediction.java │ ├── ReadOnly.java │ ├── SpringDetector.java │ └── mapself │ │ ├── MapEntry.java │ │ ├── SimpleHashMap.java │ │ └── SlowMap.java ├── chapter16 │ ├── BinaryFile.java │ ├── ChangeSystemOut.java │ ├── Constants.java │ ├── DirList.java │ ├── DirList2.java │ ├── DirList3.java │ ├── Echo.java │ ├── MakeDirectories.java │ ├── Redirecting.java │ ├── TextFile.java │ ├── io │ │ ├── BasicFileOutput.java │ │ ├── BasicFileOutput.out │ │ ├── BufferedInputFile.java │ │ ├── Data.txt │ │ ├── FileOutputShortcut.java │ │ ├── FileOutputShortcut.out │ │ ├── FormattedMemoryInput.java │ │ ├── MemoryInput.java │ │ ├── StoringAndRecoveringData.java │ │ ├── TestEOF.java │ │ ├── UsingRandomAccessFIle.java │ │ └── rtest.dat │ ├── nio │ │ ├── GetChannel.java │ │ └── data.txt │ ├── redirecting.out │ ├── textFileTest.txt │ └── textFileTest2.txt ├── chapter18 │ ├── DiningPhilosophers.java │ ├── HorseRace.java │ ├── ThreadVariations.java │ └── ToastOMatic.java ├── chapter2 │ └── DefaultValue.java ├── chapter3 │ ├── ArithmeticOperator.java │ ├── AssignmentOperator.java │ ├── AssignmentOperator2.java │ ├── BasicTypeCast.java │ ├── Exponent.java │ └── RelationOperator.java ├── chapter4 │ └── ForLoop.java ├── chapter5 │ ├── MottoHIT.java │ ├── Overload.java │ ├── StructureMethod.java │ └── Zoo.java ├── chapter7 │ ├── ClassA.java │ └── FinalParamter.java ├── chapter8 │ ├── CovariantReturnType.java │ ├── Global.java │ └── PrivateOverride.java └── chapter9 │ ├── ClassInInterface.java │ ├── InheritInnerClass.java │ ├── NestInterface.java │ ├── OuterClass.java │ └── OuterInterface.java └── vmachine ├── chapter1 ├── DirectMemoryOOM.java ├── HeapOOM.java ├── JavaVMStackOOM.java ├── JavaVMStackSOF.java └── RuntimeConstantPoolOOM.java └── chapter2 └── ReferenceCountingGC.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | .project 3 | target 4 | .DS_Store 5 | 6 | /target/ 7 | !.mvn/wrapper/maven-wrapper.jar 8 | 9 | ### STS ### 10 | .apt_generated 11 | .classpath 12 | .factorypath 13 | .project 14 | .settings 15 | .springBeans 16 | .sts4-cache 17 | 18 | ### IntelliJ IDEA ### 19 | .idea 20 | *.iws 21 | *.iml 22 | *.ipr 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /build/ 27 | /nbbuild/ 28 | /dist/ 29 | /nbdist/ 30 | /.nb-gradle/ 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Charies Gavin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /articles/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/articles/.DS_Store -------------------------------------------------------------------------------- /articles/effective-programming/common-program-design.md: -------------------------------------------------------------------------------- 1 | # 效率编程 之「通用程序设计」 2 | 3 | ### 第 1 条:将局部变量的作用域最小化 4 | 5 | 要使局部变量的作用域最小化,最有力的方法就是在第一次使用它的地方声明。局部变量的作用域从它被声明的点开始扩展,一直到外围块的结束处。如果变量是在“使用它的块”之外被声明的,当程序退出该块之后,该变量仍然是可见的;如果变量在它的目标使用区域之前或者之后被意外地使用的话,后果将可能是灾难性的。 6 | 7 | 几乎每个局部变量的声明都应该包含一个初始化表达式。如果我们还没有足够的信息来对一个变量进行有意义的初始化,就应该推迟这个声明,直到可以初始化为止。这条规则有一个例外的情况与`try-catch`语句有关。**如果一个变量被一个方法初始化,而这个方法可能会抛出一个受检的异常,该变量就必须在`try`块的内部被初始化;如果变量的值必须在`try`块的外部使用,它就必须在`try`块之前被声明,但是在`try`块之前,它还不能被“有意义地初始化”**。 8 | 9 | 循环中提供了特殊的机会来将变量的作用域最小化。无论是传统的还是高级的`for`循环,都允许声明循环变量,它们的作用域被限定在正好需要的范围之内,这个范围包括循环体,以及循环体之前的初始化、测试、更新部分。因此,如果在循环终止之后不再需要循环变量的内容,`for`循环就优先于`while`循环。考虑下面的代码片段,它包含两个`while`循环以及一个`Bug`: 10 | 11 | ``` 12 | Iterator it = list.iterator(); 13 | while (it.hasNext()) { 14 | System.out.println("列表一中的元素:" + it.next()); 15 | } 16 | 17 | Iterator it2 = list2.iterator(); 18 | while (it.hasNext()) { 19 | System.out.println("列表二中的元素:" + it.next()); 20 | } 21 | ``` 22 | 23 | 如上述代码所示,第二个循环中包含了一个“剪切-粘贴”错误:它本来是要初始化一个新的循环变量`it2`,却使用了旧的的循环变量`it`,遗憾的是,这是`it`仍然还在有效范围之内。结果就是,代码仍然可以通过编译,运行的时候也不会抛出异常,但是它所做的事情却是错误的。反之,如果上述的“剪切-粘贴”错误出现在`for`循环中,结果代码就根本不可能通过编译。此外,高级的`for-each`循环优于传统的`for`循环。考虑下面的代码片段,它也包含一个`Bug`: 24 | 25 | ``` 26 | Collection faces = Arrays.asList(Face.values()); 27 | 28 | for (Iterator i = faces.iterator(); i.hasNext(); ) { 29 | for (Iterator j = faces.iterator(); j.hasNext(); ) { 30 | System.out.println(i.next() + " " + j.next()); 31 | } 32 | } 33 | ``` 34 | 上面的问题在于,在迭代器上对外部的集合调用了太多次`next()`方法了。它应该从外部循环进行调用,以便在每一次内部循环中前一次骰子的每一面只调用一次,但它却是从内部循环调用,因此它是每一面调用一次。在用完所有面之后,就会抛出`NoSuchElementException`异常。如果真的那么不幸,并且外部集合的大小是内部集合大小的几倍,可能因为它们是相同的结合,循环就会正常终止,但是不会完成我们想要的工作。如果使用的嵌套的`for-each`循环,则不会出现上面的`Bug`,例如: 35 | 36 | ``` 37 | for (Face face1 : faces) { 38 | for (Face face2 : faces) { 39 | System.out.println(face1 + " " + face2); 40 | } 41 | } 42 | ``` 43 | 44 | 最后一种“将局部变量的作用域最小化”的方式是**使方法小而集中**。如果把两个操作合并到同一个方法中,与其中一个操作相关的局部变量就有可能会出现在执行另一个操作的代码范围之内。为了防止这种情况发生,只要把这个方法分成两个,每个方法各执行一个操作即可。 45 | 46 | ### 第 2 条:基本类型优先于装箱基本类型 47 | 48 | 在基本类型和装箱基本类型之间,有三个主要的区别: 49 | 50 | - 第一,基本类型只有值,而装箱基本类型则具有与它们的值不同的统一性。换句话说,两个装箱基本类型可以具有相同的值和不同的统一性。 51 | - 第二,基本类型只有功能完备的值,而每个装箱类型除了它对应基本类型的所有功能值之外,还有个非功能值`null`。 52 | - 最后一点区别是,基本类型通常比装箱基本类型更节省时间和空间。 53 | 54 | **对装箱基本类型运用`==`操作符几乎总是错误的**。几乎在任何一种情况下,当在一项操作中混合使用基本类型和装箱基本类型时,装箱基本类型都会自动拆箱,这种情况无一例外。如果``null`对象引用被自动拆箱的话,就会得到一个`NPE`异常。那么什么时候应该使用装箱基本类型呢?它们有几个合理的用处: 55 | 56 | - 第一个,作为集合中的元素、键和值。我们不能将基本类型放在集合中,因此必须使用装箱基本类型。 57 | - 第二个,在参数化类型中,必须使用装箱基本类型作为参数,因为 Java 不允许使用基本类型。例如,我们不能将变量声明为`List`,而应该用`List`来代替。 58 | - 最后,在进行反射的方法调用时,必须使用装箱基本类型。 59 | 60 | 总之,当可以选择的时候,基本类型要优先于装箱基本类型。基本类型更加简单,也更加快速。如果必须使用装箱基本类型,要特别小心!自动装箱减少了使用装箱基本类型的繁琐性,但是并没有减少它的风险。 61 | 62 | 63 | 64 | ---------- 65 | 66 | ———— ☆☆☆ —— 返回 -> [The Skills of Java](https://github.com/guobinhit/java-skills/blob/master/README.md) <- 目录 —— ☆☆☆ ———— 67 | -------------------------------------------------------------------------------- /articles/programming-thought/access-rights.md: -------------------------------------------------------------------------------- 1 | # 编程思想 之「访问权限控制」 2 | 3 | 访问权限控制的等级,从最大权限到最小权限依次为:`public`、`protected`、包访问权限(没有关键字)和`private`。 4 | 5 | - `public`:任何类都可以访问; 6 | - `protected`:该类的子类及同包的类可以访问; 7 | - `包访问权限`:同包的类可以访问; 8 | - `private`:只有本类的成员可以访问。 9 | 10 | 每个编译单元只能有一个`public`类,否则编译器就会报错。当编译一个`.java`文件时,在`.java`文件中的每个类都会有一个输出文件,而该输出文件的名字与`.java`文件中的每个类的名称相同,只是多了一个`.class`的后缀名。因此,我们经常会发现只要编译少量的`.java`文件,就会产生大量的`.class`文件。 11 | 12 | 访问权限修饰符`public`、`protected`和`private`在使用时,是置于类中每个成员的定义之前的,无论它是一个方法还是一个域。如果不提供任何访问权限修饰符,则意味着它是“包访问权限”。 13 | 14 | 如果创建了一个新包,并从另一个包中继承类,那么唯一可以访问的成员就是源包的`public`成员。当然,如果在同一个包中继承类,就可以访问所有拥有包访问权限的成员。`protected`也提供包访问权限,也就是说,相同包内的其他类也可以访问`protected`元素。 15 | 16 | 为了控制某个类的访问权限,修饰词必须出现在关键字`class`之前。此外,还有一些额外的限制: 17 | 18 | - 每个编译单元(文件)都只能有一个`public`类; 19 | - `public`类的名称必须完全与含有该编译单元的文件名相匹配,包括大小写; 20 | - 虽然不是很常用,但编译单元内完全不带`public`类也是可能的。 21 | 22 | 最后,要注意:**类既不可以是`private`的(这样会使得除该类之外,其他任何类都不可以访问它),也不可以是`protected`的**。事实上,一个内部类可以是`private`或者`protected`的,但这仅是一个特例。 23 | 24 | ---------- 25 | 26 | ———— ☆☆☆ —— 返回 -> [The Skills of Java](https://github.com/guobinhit/java-skills/blob/master/README.md) <- 目录 —— ☆☆☆ ———— 27 | -------------------------------------------------------------------------------- /articles/programming-thought/concurrency.md: -------------------------------------------------------------------------------- 1 | # 编程思想 之「并发」 2 | 3 | 4 | 5 | ---------- 6 | 7 | ———— ☆☆☆ —— 返回 -> [The Skills of Java](https://github.com/guobinhit/java-skills/blob/master/README.md) <- 目录 —— ☆☆☆ ———— 8 | -------------------------------------------------------------------------------- /articles/programming-thought/enum-annotation.md: -------------------------------------------------------------------------------- 1 | # 编程思想 之「枚举类型、注解」 2 | 3 | 4 | 5 | ---------- 6 | 7 | ———— ☆☆☆ —— 返回 -> [The Skills of Java](https://github.com/guobinhit/java-skills/blob/master/README.md) <- 目录 —— ☆☆☆ ———— 8 | -------------------------------------------------------------------------------- /articles/programming-thought/language-guide.md: -------------------------------------------------------------------------------- 1 | # 编程思想 之「语言导论」 2 | 3 | ![java-icon](https://github.com/guobinhit/java-skills/blob/master/images/programming-thought/language-guide/java-icon.png) 4 | 5 | > **Java 发展史** 6 | 7 | Java 是一门面向对象的编程语言,它不仅吸收了 C++ 语言的各种优点,还摒弃了 C++ 里难以理解的多重继承、指针等概念,因此 Java 语言具有功能强大和简单易用两个特征。此外,Java 还具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点。Java 语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。 8 | 9 | Java 语言缘起于 1991 年 Sun 成立的一个名为 Green 的项目小组,这个由詹姆斯·高斯林、帕特里克、麦克·舍林丹和其他几个工程师一起组成的工作小组在加利福尼亚州门洛帕克市沙丘路的一个小工作室里面研究开发新技术,专攻计算机在家电产品上的嵌入式应用,而这个小组的新技术成果就是 Java 语言的前身,名为 Oak 的面向对象编程语言。 10 | 11 | 虽然 Oak 是一门不错的面向对象编程语言,但是在随后的几年内,Oak 并没有受到市场的青睐。直到 1995 年,互联网的蓬勃发展给了 Oak 机会,Sun 公司首先推出了基于 Oak 的可以嵌入网页并且可以随同网页在网络上传输的 Applet(一种将小程序嵌入到网页中进行执行的技术),并于同年 5 月将 Oak 更名为 Java,这里还有一个小插曲,在申请注册商标时,由于发现 Oak 已经被人使用了,再想了一系列名字之后,最终,使用了提议者在喝一杯 Java 咖啡时无意提到的 Java 词语,Java 语言就此正式诞生。 12 | 13 | 自 1991 年 1 月 Sun 公司发布 Java 第一个开发工具包(JDK 1.0)至 2017 年 9 月 Oracle 发布 Java SE 9.0 期间,Java 经历了众多的迭代与更新,其中变化最大的一次更新当属 2004 年 9 月 30 日,J2SE 1.5 发布,这是 Java 语言发展史上的又一里程碑(第一个里程碑为 1991 年 Sun 发布 JDK 1.0,它标志着 Java 成为了一种独立的开发工具)。为了表示该版本的重要性,J2SE 1.5 更名为 Java SE 5.0(内部版本号 1.5.0),代号为 Tiger,Tiger 包含了从 1996 年发布 1.0 版本以来的最重大的更新,其中包括泛型、基本类型的自动装箱、改进的循环、枚举类型、注解、格式化 I/O 及可变参数等。 14 | 15 | > **面向对象** 16 | 17 | 亚里士多德大概是第一个深入研究类型的哲学家,他曾提出过鸟类和鱼类这样的概念。所有的对象都是唯一的,但是同时也是具有相同的特性和行为的对象所归属的类的一部分。在计算机语言的世界中,第一个面向对象的编程语言 Simula-67 就采用了上述的面向对象的思想,它在程序中使用关键字`class`来引入新的类型,Java 语言同样如此。 18 | 19 | 虽然 Simula-67 是第一个面向对象的编程语言,但它并不成功。第一个成功面向对象的语言是 Smalltalk ,同时它也是 Java 所基于的语言之一。Alan Kay(他是 Smalltalk 面向对象编程环境语言的发明人之一,也是面向对象编程思想的创始人之一,他还是笔记本电脑最早的构想者和现代 Windows GUI 的最初尝试者)曾总结了 Smalltalk 的五个基本特性,这些特性正是纯粹的面向对象的编程语言所该具有的,包括: 20 | 21 | - 万物皆对象; 22 | - 这是面向对象编程的终极奥义。 23 | - 程序是对象的集合,它们通过发生消息来告知彼此所要做的事情; 24 | - 简单点说,程序中包含不同的对象,对象之间通过调用方法(发送消息)来达到所要实现的具体行为。 25 | - 每个对象都有自己的由其他的对象所构成的存储; 26 | - 可以通过创建包含现有对象的方式来创建新的对象。 27 | - 每个对象都拥有其类型; 28 | - 每个对象都是某个类的实例,不同的类的区别是就可以接收不同的消息。 29 | - 某一特定类型的所有对象都可以接收同样的消息。 30 | - 如 Java 语言中的多态,导出类可以接收任何发给基类的消息。 31 | 32 | 在理想的面向对象的编程语言中,每个对象都有一个接口(并非绝对,例如我们单纯的想定义一个对象来表示某种类型体系,我们就可以不在对象里面定义接口,这里的接口指方法或者函数),我们通过发送消息(调用对象的接口)来告知对象我们要实现什么行为或者动作。反言之,每个对象都提供服务,我们通过想要实现的服务来确定给哪个对象发送消息。 33 | 34 | 相比于「非面向对象编程」的编译器产生的函数调用引起的所谓的「前期绑定」,即编译器产生一个对于具体函数名字的调用,而运行时将这个调用解析到将要执行的代码的绝对地址;「面向对象编程」最重要的地方就是:编译器不可能产生传统意义上的函数调用,而是使用了「后期绑定」的概念,即当向对象发送消息时,被调用的代码直到运行时才能确定。 35 | 36 | 除上述内容之外,Java 还提供了很多其他的特性来为我们编程做助力,例如单根(Object)继承体系、容器类、参数化类型(泛型)、高效的对象创建及生命周期(垃圾回收机制)、异常和错误处理、并发编程等。Java 的魅力,并不止于此! 37 | 38 | 39 | ---------- 40 | 41 | ———— ☆☆☆ —— 返回 -> [The Skills of Java](https://github.com/guobinhit/java-skills/blob/master/README.md) <- 目录 —— ☆☆☆ ———— 42 | 43 | -------------------------------------------------------------------------------- /images/effective-programming/enum-annotaion/run-tests.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/effective-programming/enum-annotaion/run-tests.png -------------------------------------------------------------------------------- /images/effective-programming/generic-paradigm2/simple-stack-pop-all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/effective-programming/generic-paradigm2/simple-stack-pop-all.png -------------------------------------------------------------------------------- /images/effective-programming/generic-paradigm2/simple-stack-push-all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/effective-programming/generic-paradigm2/simple-stack-push-all.png -------------------------------------------------------------------------------- /images/effective-programming/method/assertion-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/effective-programming/method/assertion-error.png -------------------------------------------------------------------------------- /images/effective-programming/method/configurations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/effective-programming/method/configurations.png -------------------------------------------------------------------------------- /images/effective-programming/method/period-test-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/effective-programming/method/period-test-2.png -------------------------------------------------------------------------------- /images/effective-programming/method/period-test-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/effective-programming/method/period-test-3.png -------------------------------------------------------------------------------- /images/effective-programming/method/period-test-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/effective-programming/method/period-test-4.png -------------------------------------------------------------------------------- /images/effective-programming/method/period-test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/effective-programming/method/period-test.png -------------------------------------------------------------------------------- /images/programming-thought/array-container/array-options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/array-container/array-options.png -------------------------------------------------------------------------------- /images/programming-thought/array-container/generic-and-upcasting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/array-container/generic-and-upcasting.png -------------------------------------------------------------------------------- /images/programming-thought/array-container/test-container.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/array-container/test-container.png -------------------------------------------------------------------------------- /images/programming-thought/control-process/for-loop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/control-process/for-loop.png -------------------------------------------------------------------------------- /images/programming-thought/deep-container/full-container-taxonomy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/deep-container/full-container-taxonomy.png -------------------------------------------------------------------------------- /images/programming-thought/deep-container/simple-hash-map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/deep-container/simple-hash-map.png -------------------------------------------------------------------------------- /images/programming-thought/generic-paradigm/erased-type-equivalence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/generic-paradigm/erased-type-equivalence.png -------------------------------------------------------------------------------- /images/programming-thought/handle-exception/catch-a-exception.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/handle-exception/catch-a-exception.png -------------------------------------------------------------------------------- /images/programming-thought/handle-exception/catch-a-new-exception.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/handle-exception/catch-a-new-exception.png -------------------------------------------------------------------------------- /images/programming-thought/handle-exception/catch-simple-exception.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/handle-exception/catch-simple-exception.png -------------------------------------------------------------------------------- /images/programming-thought/handle-exception/declaration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/handle-exception/declaration.png -------------------------------------------------------------------------------- /images/programming-thought/handle-exception/initial-test-finally.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/handle-exception/initial-test-finally.png -------------------------------------------------------------------------------- /images/programming-thought/handle-exception/runtime-exception.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/handle-exception/runtime-exception.png -------------------------------------------------------------------------------- /images/programming-thought/handle-exception/test-exception.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/handle-exception/test-exception.png -------------------------------------------------------------------------------- /images/programming-thought/handle-exception/tips-exception.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/handle-exception/tips-exception.png -------------------------------------------------------------------------------- /images/programming-thought/initial-and-clean/class-animal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/initial-and-clean/class-animal.png -------------------------------------------------------------------------------- /images/programming-thought/initial-and-clean/motto-hit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/initial-and-clean/motto-hit.png -------------------------------------------------------------------------------- /images/programming-thought/interface-innerclass/anonymous-inner-class2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/interface-innerclass/anonymous-inner-class2.png -------------------------------------------------------------------------------- /images/programming-thought/interface-innerclass/outer-inner-class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/interface-innerclass/outer-inner-class.png -------------------------------------------------------------------------------- /images/programming-thought/language-guide/java-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/language-guide/java-icon.png -------------------------------------------------------------------------------- /images/programming-thought/operator/test-arithmetic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/operator/test-arithmetic.png -------------------------------------------------------------------------------- /images/programming-thought/operator/test-assignment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/operator/test-assignment.png -------------------------------------------------------------------------------- /images/programming-thought/operator/test-relation-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/operator/test-relation-2.png -------------------------------------------------------------------------------- /images/programming-thought/operator/test-relation-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/operator/test-relation-3.png -------------------------------------------------------------------------------- /images/programming-thought/operator/test-relation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/operator/test-relation.png -------------------------------------------------------------------------------- /images/programming-thought/polymorphic/covariant-return-type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/polymorphic/covariant-return-type.png -------------------------------------------------------------------------------- /images/programming-thought/polymorphic/extends-system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/polymorphic/extends-system.png -------------------------------------------------------------------------------- /images/programming-thought/polymorphic/global.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/polymorphic/global.png -------------------------------------------------------------------------------- /images/programming-thought/polymorphic/private-override.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/polymorphic/private-override.png -------------------------------------------------------------------------------- /images/programming-thought/reuse-class/class-a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/reuse-class/class-a.png -------------------------------------------------------------------------------- /images/programming-thought/rtti-and-reflect/compare-class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/rtti-and-reflect/compare-class.png -------------------------------------------------------------------------------- /images/programming-thought/rtti-and-reflect/dot-class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/rtti-and-reflect/dot-class.png -------------------------------------------------------------------------------- /images/programming-thought/rtti-and-reflect/load-class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/rtti-and-reflect/load-class.png -------------------------------------------------------------------------------- /images/programming-thought/rtti-and-reflect/test-reflect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/rtti-and-reflect/test-reflect.png -------------------------------------------------------------------------------- /images/programming-thought/string/hi-girl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/string/hi-girl.png -------------------------------------------------------------------------------- /images/programming-thought/string/javap-c-class.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/string/javap-c-class.png -------------------------------------------------------------------------------- /images/programming-thought/string/stack-over-flow-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/string/stack-over-flow-error.png -------------------------------------------------------------------------------- /images/programming-thought/string/string-regular-expression.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/string/string-regular-expression.png -------------------------------------------------------------------------------- /images/programming-thought/string/test-reg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/programming-thought/string/test-reg.png -------------------------------------------------------------------------------- /images/virtual-machine/vmo-runtime/runtime-data-area.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/images/virtual-machine/vmo-runtime/runtime-data-area.png -------------------------------------------------------------------------------- /javaskills/.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | .project 3 | target 4 | .DS_Store 5 | 6 | /target/ 7 | !.mvn/wrapper/maven-wrapper.jar 8 | 9 | ### STS ### 10 | .apt_generated 11 | .classpath 12 | .factorypath 13 | .project 14 | .settings 15 | .springBeans 16 | .sts4-cache 17 | 18 | ### IntelliJ IDEA ### 19 | .idea 20 | *.iws 21 | *.iml 22 | *.ipr 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /build/ 27 | /nbbuild/ 28 | /dist/ 29 | /nbdist/ 30 | /.nb-gradle/ -------------------------------------------------------------------------------- /javaskills/out/production/javaskills/com/hit/thought/chapter1/LanguageGuide.md: -------------------------------------------------------------------------------- 1 | > **Java 发展史** 2 | 3 | Java 是一门面向对象的编程语言,它不仅吸收了 C++ 语言的各种优点,还摒弃了 C++ 里难以理解的多重继承、指针等概念,因此 Java 语言具有功能强大和简单易用两个特征。此外,Java 还具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点。Java 语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。 4 | 5 | Java 语言缘起于 1991 年 Sun 成立的一个名为 Green 的项目小组,这个由詹姆斯·高斯林、帕特里克、麦克·舍林丹和其他几个工程师一起组成的工作小组在加利福尼亚州门洛帕克市沙丘路的一个小工作室里面研究开发新技术,专攻计算机在家电产品上的嵌入式应用,而这个小组的新技术成果就是 Java 语言的前身,名为 Oak 的面向对象编程语言。 6 | 7 | 虽然 Oak 是一门不错的面向对象编程语言,但是在随后的几年内,Oak 并没有受到市场的青睐。直到 1995 年,互联网的蓬勃发展给了 Oak 机会,Sun 公司首先推出了基于 Oak 的可以嵌入网页并且可以随同网页在网络上传输的 Applet(一种将小程序嵌入到网页中进行执行的技术),并于同年 5 月将 Oak 更名为 Java,这里还有一个小插曲,在申请注册商标时,由于发现 Oak 已经被人使用了,再想了一系列名字之后,最终,使用了提议者在喝一杯 Java 咖啡时无意提到的 Java 词语,Java 语言就此正式诞生。 8 | 9 | 自 1991 年 1 月 Sun 公司发布 Java 第一个开发工具包(JDK 1.0)至 2017 年 9 月 Oracle 发布 Java SE 9.0 期间,Java 经历了众多的迭代与更新,其中变化最大的一次更新当属 2004 年 9 月 30 日,J2SE 1.5 发布,这是 Java 语言发展史上的又一里程碑(第一个里程碑为 1991 年 Sun 发布 JDK 1.0,它标志着 Java 成为了一种独立的开发工具)。为了表示该版本的重要性,J2SE 1.5 更名为 Java SE 5.0(内部版本号 1.5.0),代号为 Tiger,Tiger 包含了从 1996 年发布 1.0 版本以来的最重大的更新,其中包括泛型、基本类型的自动装箱、改进的循环、枚举类型、注解、格式化 I/O 及可变参数等。 10 | 11 | > **面向对象** 12 | 13 | 亚里士多德大概是第一个深入研究类型的哲学家,他曾提出过鸟类和鱼类这样的概念。所有的对象都是唯一的,但是同时也是具有相同的特性和行为的对象所归属的类的一部分。在计算机语言的世界中,第一个面向对象的编程语言 Simula-67 就采用了上述的面向对象的思想,它在程序中使用关键字`class`来引入新的类型,Java 语言同样如此。 14 | 15 | 虽然 Simula-67 是第一个面向对象的编程语言,但它并不成功。第一个成功面向对象的语言是 Smalltalk ,同时它也是 Java 所基于的语言之一。Alan Kay(他是 Smalltalk 面向对象编程环境语言的发明人之一,也是面向对象编程思想的创始人之一,他还是笔记本电脑最早的构想者和现代 Windows GUI 的最初尝试者)曾总结了 Smalltalk 的五个基本特性,这些特性正是纯粹的面向对象的编程语言所该具有的,包括: 16 | 17 | - 万物皆对象; 18 | - 这是面向对象编程的终极奥义。 19 | - 程序是对象的集合,它们通过发生消息来告知彼此所要做的事情; 20 | - 简单点说,程序中包含不同的对象,对象之间通过调用方法(发送消息)来达到所要实现的具体行为。 21 | - 每个对象都有自己的由其他的对象所构成的存储; 22 | - 可以通过创建包含现有对象的方式来创建新的对象。 23 | - 每个对象都拥有其类型; 24 | - 每个对象都是某个类的实例,不同的类的区别是就可以接收不同的消息。 25 | - 某一特定类型的所有对象都可以接收同样的消息。 26 | - 如 Java 语言中的多态,导出类可以接收任何发给基类的消息。 27 | 28 | 在理想的面向对象的编程语言中,每个对象都有一个接口(并非绝对,例如我们单纯的想定义一个对象来表示某种类型体系,我们就可以不在对象里面定义接口,这里的接口指方法或者函数),我们通过发送消息(调用对象的接口)来告知对象我们要实现什么行为或者动作。反言之,每个对象都提供服务,我们通过想要实现的服务来确定给哪个对象发送消息。 29 | 30 | 相比于「非面向对象编程」的编译器产生的函数调用引起的所谓的「前期绑定」,即编译器产生一个对于具体函数名字的调用,而运行时将这个调用解析到将要执行的代码的绝对地址;「面向对象编程」最重要的地方就是:编译器不可能产生传统意义上的函数调用,而是使用了「后期绑定」的概念,即当向对象发送消息时,被调用的代码直到运行时才能确定。 31 | 32 | 除上述内容之外,Java 还提供了很多其他的特性来为我们编程做助力,例如单根(Object)继承体系、容器类、参数化类型(泛型)、高效的对象创建及生命周期(垃圾回收机制)、异常和错误处理、并发编程等。Java 的魅力,并不止于此! 33 | -------------------------------------------------------------------------------- /javaskills/out/production/javaskills/com/hit/thought/chapter16/io/BasicFileOutput.out: -------------------------------------------------------------------------------- 1 | 1 : package com.hit.thought.chapter16.io; 2 | 2 : 3 | 3 : import com.hit.thought.chapter16.Constants; 4 | 4 : 5 | 5 : import java.io.*; 6 | 6 : 7 | 7 : /** 8 | 8 : * author:Charies Gavin 9 | 9 : * date:2018/5/6,14:30 10 | 10 : * https:github.com/guobinhit 11 | 11 : * description:缓存输入与输出 12 | 12 : */ 13 | 13 : public class BasicFileOutput { 14 | 14 : private static String file = Constants.FILE_ABSOLUTE_PATH + "BasicFileOutput.out"; 15 | 15 : 16 | 16 : public static void main(String[] args) throws IOException { 17 | 17 : BufferedReader in = new BufferedReader( 18 | 18 : new StringReader( 19 | 19 : BufferedInputFile.read(Constants.FILE_ABSOLUTE_PATH + "BasicFileOutput.java") 20 | 20 : ) 21 | 21 : ); 22 | 22 : 23 | 23 : /** 24 | 24 : * FileWriter 对象可以向文件写入数据 25 | 25 : */ 26 | 26 : PrintWriter out = new PrintWriter( 27 | 27 : new BufferedWriter( 28 | 28 : new FileWriter(file) 29 | 29 : ) 30 | 30 : ); 31 | 31 : 32 | 32 : // 用于显示行号 33 | 33 : int lineCount = 1; 34 | 34 : String s; 35 | 35 : while ((s = in.readLine()) != null) { 36 | 36 : out.println(lineCount++ + " : " + s); 37 | 37 : } 38 | 38 : out.close(); 39 | 39 : System.out.println(BufferedInputFile.read(file)); 40 | 40 : } 41 | 41 : } 42 | -------------------------------------------------------------------------------- /javaskills/out/production/javaskills/com/hit/thought/chapter16/io/Data.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/javaskills/out/production/javaskills/com/hit/thought/chapter16/io/Data.txt -------------------------------------------------------------------------------- /javaskills/out/production/javaskills/com/hit/thought/chapter16/io/FileOutputShortcut.out: -------------------------------------------------------------------------------- 1 | 1 : package com.hit.thought.chapter16.io; 2 | 2 : 3 | 3 : import com.hit.thought.chapter16.Constants; 4 | 4 : 5 | 5 : import java.io.*; 6 | 6 : 7 | 7 : /** 8 | 8 : * author:Charies Gavin 9 | 9 : * date:2018/5/6,15:00 10 | 10 : * https:github.com/guobinhit 11 | 11 : * description:优化缓存输入和输出 12 | 12 : */ 13 | 13 : public class FileOutputShortcut { 14 | 14 : private static String file = Constants.FILE_ABSOLUTE_PATH + "FileOutputShortcut.out"; 15 | 15 : 16 | 16 : public static void main(String[] args) throws IOException { 17 | 17 : BufferedReader in = new BufferedReader( 18 | 18 : new StringReader( 19 | 19 : BufferedInputFile.read(Constants.FILE_ABSOLUTE_PATH + "FileOutputShortcut.java") 20 | 20 : ) 21 | 21 : ); 22 | 22 : 23 | 23 : /** 24 | 24 : * 在 Java SE5 中,PrintWriter 新增了一个辅助构造器, 25 | 25 : * 使得我们不必在每次希望创建文本文件并向其中写入时, 26 | 26 : * 都去执行所有的装饰工作 27 | 27 : */ 28 | 28 : PrintWriter out = new PrintWriter(file); 29 | 29 : 30 | 30 : // 用于显示行号 31 | 31 : int lineCount = 1; 32 | 32 : String s; 33 | 33 : while ((s = in.readLine()) != null) { 34 | 34 : out.println(lineCount++ + " : " + s); 35 | 35 : } 36 | 36 : out.close(); 37 | 37 : System.out.println(BufferedInputFile.read(file)); 38 | 38 : } 39 | 39 : } 40 | -------------------------------------------------------------------------------- /javaskills/out/production/javaskills/com/hit/thought/chapter16/io/rtest.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/javaskills/out/production/javaskills/com/hit/thought/chapter16/io/rtest.dat -------------------------------------------------------------------------------- /javaskills/out/production/javaskills/com/hit/thought/chapter16/nio/data.txt: -------------------------------------------------------------------------------- 1 | Hello World See U! -------------------------------------------------------------------------------- /javaskills/out/production/javaskills/com/hit/thought/chapter16/redirecting.out: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter16; 2 | 3 | import java.io.*; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/6/26,9:21 8 | * https:github.com/guobinhit 9 | * description:重定向标准 IO 流 10 | */ 11 | public class Redirecting { 12 | public static void main(String[] args) throws IOException { 13 | PrintStream console = System.out; 14 | BufferedInputStream in = new BufferedInputStream( 15 | new FileInputStream(Constants.FILE_ABSOLUTE_PATH_EXCLUDE_IO + "Redirecting.java") 16 | ); 17 | PrintStream out = new PrintStream( 18 | new BufferedOutputStream( 19 | new FileOutputStream(Constants.FILE_ABSOLUTE_PATH_EXCLUDE_IO + "redirecting.out") 20 | ) 21 | ); 22 | System.setIn(in); 23 | System.setOut(out); 24 | System.setErr(out); 25 | BufferedReader br = new BufferedReader( 26 | new InputStreamReader(System.in) 27 | ); 28 | String s; 29 | while ((s = br.readLine()) != null) { 30 | System.out.println(s); 31 | } 32 | out.close(); 33 | System.setOut(console); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/concurrent/chapter1/CachedFactorizer.java: -------------------------------------------------------------------------------- 1 | package com.hit.concurrent.chapter1; 2 | 3 | import javax.servlet.*; 4 | import java.io.IOException; 5 | import java.math.BigInteger; 6 | 7 | /** 8 | * author:Charies Gavin 9 | * date:2018/10/21,18:52 10 | * https:github.com/guobinhit 11 | * description:线程安全类,更细的锁粒度 12 | */ 13 | public class CachedFactorizer implements Servlet { 14 | 15 | private BigInteger lastNumber; 16 | private BigInteger[] lastFactors; 17 | private long hits; 18 | private long cacheHits; 19 | 20 | public synchronized long getHits() { 21 | return hits; 22 | } 23 | 24 | public synchronized long getCacheHits() { 25 | return cacheHits; 26 | } 27 | 28 | @Override 29 | public synchronized void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { 30 | BigInteger i = extractFromRequest(servletRequest); 31 | BigInteger[] factors = null; 32 | synchronized (this) { 33 | ++hits; 34 | if (i.equals(lastNumber)) { 35 | ++cacheHits; 36 | factors = lastFactors.clone(); 37 | } 38 | } 39 | if (factors == null) { 40 | factors = factor(i); 41 | synchronized (this) { 42 | lastNumber = i; 43 | lastFactors = factors.clone(); 44 | } 45 | } 46 | encodeIntoResponse(servletResponse, factors); 47 | } 48 | 49 | private BigInteger extractFromRequest(ServletRequest servletRequest) { 50 | return BigInteger.ZERO; 51 | } 52 | 53 | private BigInteger[] factor(BigInteger i) { 54 | BigInteger[] factors = {BigInteger.ZERO}; 55 | return factors; 56 | } 57 | 58 | private void encodeIntoResponse(ServletResponse servletResponse, java.math.BigInteger[] factors) { 59 | 60 | } 61 | 62 | @Override 63 | public String getServletInfo() { 64 | return null; 65 | } 66 | 67 | @Override 68 | public void destroy() { 69 | 70 | } 71 | 72 | @Override 73 | public void init(ServletConfig servletConfig) throws ServletException { 74 | 75 | } 76 | 77 | @Override 78 | public ServletConfig getServletConfig() { 79 | return null; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/concurrent/chapter1/CountingFactorizer.java: -------------------------------------------------------------------------------- 1 | package com.hit.concurrent.chapter1; 2 | 3 | import javax.servlet.*; 4 | import java.io.IOException; 5 | import java.math.BigInteger; 6 | import java.util.concurrent.atomic.AtomicLong; 7 | 8 | /** 9 | * author:Charies Gavin 10 | * date:2018/10/21,17:16 11 | * https:github.com/guobinhit 12 | * description:用现有的原子类来构建线程安全类 13 | */ 14 | public class CountingFactorizer implements Servlet { 15 | private final AtomicLong count = new AtomicLong(0); 16 | 17 | public long getCount() { 18 | return count.get(); 19 | } 20 | 21 | @Override 22 | public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { 23 | BigInteger i = extractFromRequest(servletRequest); 24 | BigInteger[] factors = factor(i); 25 | count.incrementAndGet(); 26 | encodeIntoResponse(servletResponse, factors); 27 | } 28 | 29 | private BigInteger extractFromRequest(ServletRequest servletRequest) { 30 | return BigInteger.ZERO; 31 | } 32 | 33 | private BigInteger[] factor(BigInteger i) { 34 | BigInteger[] factors = {BigInteger.ZERO}; 35 | return factors; 36 | } 37 | 38 | private void encodeIntoResponse(ServletResponse servletResponse, java.math.BigInteger[] factors) { 39 | 40 | } 41 | 42 | @Override 43 | public String getServletInfo() { 44 | return null; 45 | } 46 | 47 | @Override 48 | public void destroy() { 49 | 50 | } 51 | 52 | @Override 53 | public void init(ServletConfig servletConfig) throws ServletException { 54 | 55 | } 56 | 57 | @Override 58 | public ServletConfig getServletConfig() { 59 | return null; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/concurrent/chapter1/StatelessFactorizer.java: -------------------------------------------------------------------------------- 1 | package com.hit.concurrent.chapter1; 2 | 3 | import javax.servlet.*; 4 | import java.io.IOException; 5 | import java.math.BigInteger; 6 | 7 | /** 8 | * author:Charies Gavin 9 | * date:2018/10/21,16:35 10 | * https:github.com/guobinhit 11 | * description:无状态的类是线程安全类 12 | */ 13 | public class StatelessFactorizer implements Servlet { 14 | 15 | @Override 16 | public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { 17 | BigInteger i = extractFromRequest(servletRequest); 18 | BigInteger[] factors = factor(i); 19 | encodeIntoResponse(servletResponse, factors); 20 | } 21 | 22 | private BigInteger extractFromRequest(ServletRequest servletRequest) { 23 | return BigInteger.ZERO; 24 | } 25 | 26 | private BigInteger[] factor(BigInteger i) { 27 | BigInteger[] factors = {BigInteger.ZERO}; 28 | return factors; 29 | } 30 | 31 | private void encodeIntoResponse(ServletResponse servletResponse, java.math.BigInteger[] factors) { 32 | 33 | } 34 | 35 | @Override 36 | public String getServletInfo() { 37 | return null; 38 | } 39 | 40 | @Override 41 | public void destroy() { 42 | 43 | } 44 | 45 | @Override 46 | public void init(ServletConfig servletConfig) throws ServletException { 47 | 48 | } 49 | 50 | @Override 51 | public ServletConfig getServletConfig() { 52 | return null; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/concurrent/chapter1/SynchronizedFactorizer.java: -------------------------------------------------------------------------------- 1 | package com.hit.concurrent.chapter1; 2 | 3 | import javax.servlet.*; 4 | import java.io.IOException; 5 | import java.math.BigInteger; 6 | 7 | /** 8 | * author:Charies Gavin 9 | * date:2018/10/21,17:57 10 | * https:github.com/guobinhit 11 | * description:用 synchronized 来构建线程安全类 12 | */ 13 | public class SynchronizedFactorizer implements Servlet { 14 | 15 | private BigInteger lastNumber; 16 | private BigInteger[] lastFactors; 17 | 18 | @Override 19 | public synchronized void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { 20 | BigInteger i = extractFromRequest(servletRequest); 21 | if (i.equals(lastNumber)) { 22 | encodeIntoResponse(servletResponse, lastFactors); 23 | } else { 24 | BigInteger[] factors = factor(i); 25 | lastNumber = i; 26 | lastFactors = factors; 27 | encodeIntoResponse(servletResponse, factors); 28 | } 29 | } 30 | 31 | private BigInteger extractFromRequest(ServletRequest servletRequest) { 32 | return BigInteger.ZERO; 33 | } 34 | 35 | private BigInteger[] factor(BigInteger i) { 36 | BigInteger[] factors = {BigInteger.ZERO}; 37 | return factors; 38 | } 39 | 40 | private void encodeIntoResponse(ServletResponse servletResponse, java.math.BigInteger[] factors) { 41 | 42 | } 43 | 44 | @Override 45 | public String getServletInfo() { 46 | return null; 47 | } 48 | 49 | @Override 50 | public void destroy() { 51 | 52 | } 53 | 54 | @Override 55 | public void init(ServletConfig servletConfig) throws ServletException { 56 | 57 | } 58 | 59 | @Override 60 | public ServletConfig getServletConfig() { 61 | return null; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/concurrent/chapter1/UnsafeCachingFactorizer.java: -------------------------------------------------------------------------------- 1 | package com.hit.concurrent.chapter1; 2 | 3 | import javax.servlet.*; 4 | import java.io.IOException; 5 | import java.math.BigInteger; 6 | import java.util.concurrent.atomic.AtomicReference; 7 | 8 | /** 9 | * author:Charies Gavin 10 | * date:2018/10/21,17:28 11 | * https:github.com/guobinhit 12 | * description:非线程安全类 13 | */ 14 | public class UnsafeCachingFactorizer implements Servlet { 15 | 16 | private final AtomicReference lastNumber = 17 | new AtomicReference(); 18 | 19 | private final AtomicReference lastFactors = 20 | new AtomicReference(); 21 | 22 | @Override 23 | public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { 24 | BigInteger i = extractFromRequest(servletRequest); 25 | if (i.equals(lastNumber.get())) { 26 | encodeIntoResponse(servletResponse, lastFactors.get()); 27 | } else { 28 | BigInteger[] factors = factor(i); 29 | lastNumber.set(i); 30 | lastFactors.set(factors); 31 | encodeIntoResponse(servletResponse, factors); 32 | } 33 | } 34 | 35 | private BigInteger extractFromRequest(ServletRequest servletRequest) { 36 | return BigInteger.ZERO; 37 | } 38 | 39 | private BigInteger[] factor(BigInteger i) { 40 | BigInteger[] factors = {BigInteger.ZERO}; 41 | return factors; 42 | } 43 | 44 | private void encodeIntoResponse(ServletResponse servletResponse, java.math.BigInteger[] factors) { 45 | 46 | } 47 | 48 | @Override 49 | public String getServletInfo() { 50 | return null; 51 | } 52 | 53 | @Override 54 | public void destroy() { 55 | 56 | } 57 | 58 | @Override 59 | public void init(ServletConfig servletConfig) throws ServletException { 60 | 61 | } 62 | 63 | @Override 64 | public ServletConfig getServletConfig() { 65 | return null; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/concurrent/chapter1/UnsafeCountingFactorizer.java: -------------------------------------------------------------------------------- 1 | package com.hit.concurrent.chapter1; 2 | 3 | import javax.servlet.*; 4 | import java.io.IOException; 5 | import java.math.BigInteger; 6 | 7 | /** 8 | * author:Charies Gavin 9 | * date:2018/10/21,16:55 10 | * https:github.com/guobinhit 11 | * description:非线程安全类,存在竞态条件 12 | */ 13 | public class UnsafeCountingFactorizer implements Servlet { 14 | private long count = 0; 15 | 16 | public long getCount() { 17 | return count; 18 | } 19 | 20 | @Override 21 | public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { 22 | BigInteger i = extractFromRequest(servletRequest); 23 | BigInteger[] factors = factor(i); 24 | ++count; 25 | encodeIntoResponse(servletResponse, factors); 26 | } 27 | 28 | private BigInteger extractFromRequest(ServletRequest servletRequest) { 29 | return BigInteger.ZERO; 30 | } 31 | 32 | private BigInteger[] factor(BigInteger i) { 33 | BigInteger[] factors = {BigInteger.ZERO}; 34 | return factors; 35 | } 36 | 37 | private void encodeIntoResponse(ServletResponse servletResponse, java.math.BigInteger[] factors) { 38 | 39 | } 40 | 41 | @Override 42 | public String getServletInfo() { 43 | return null; 44 | } 45 | 46 | @Override 47 | public void destroy() { 48 | 49 | } 50 | 51 | @Override 52 | public void init(ServletConfig servletConfig) throws ServletException { 53 | 54 | } 55 | 56 | @Override 57 | public ServletConfig getServletConfig() { 58 | return null; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/concurrent/chapter1/UnsafeSequence.java: -------------------------------------------------------------------------------- 1 | package com.hit.concurrent.chapter1; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/10/21,10:32 6 | * https:github.com/guobinhit 7 | * description:非线程安全类,存在竞态条件 8 | */ 9 | public class UnsafeSequence { 10 | private int value; 11 | 12 | /** 13 | * 返回唯一的数值 14 | */ 15 | public int getNext() { 16 | return value++; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/concurrent/chapter1/Widget.java: -------------------------------------------------------------------------------- 1 | package com.hit.concurrent.chapter1; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/10/21,18:06 6 | * https:github.com/guobinhit 7 | * description:线程安全类,内置锁可重入 8 | */ 9 | public class Widget { 10 | public synchronized void doSomething() { 11 | } 12 | } 13 | 14 | class LoggingWidget extends Widget { 15 | public synchronized void doSomething() { 16 | System.out.println("Hello World"); 17 | super.doSomething(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/concurrent/chapter2/NoVisibility.java: -------------------------------------------------------------------------------- 1 | package com.hit.concurrent.chapter2; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/10/27,10:12 6 | * https:github.com/guobinhit 7 | * description:可能出现无限循环 8 | */ 9 | public class NoVisibility { 10 | private static boolean ready; 11 | private static int number; 12 | 13 | public static class ReaderThread extends Thread { 14 | public void run() { 15 | while (!ready) { 16 | Thread.yield(); 17 | } 18 | System.out.println(number); 19 | } 20 | } 21 | 22 | public static void main(String[] args) { 23 | new ReaderThread().start(); 24 | number = 20151120; 25 | ready = true; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/concurrent/chapter2/PersonSet.java: -------------------------------------------------------------------------------- 1 | package com.hit.concurrent.chapter2; 2 | 3 | import java.util.Collections; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | 7 | /** 8 | * author:Charies Gavin 9 | * date:2018/11/3,13:31 10 | * https:github.com/guobinhit 11 | * description:安全性委托 12 | */ 13 | public class PersonSet { 14 | private final Set mySet = new HashSet(); 15 | 16 | private final Set safeMySet = Collections.synchronizedSet(mySet); 17 | 18 | public void addPerson(Person p) { 19 | safeMySet.add(p); 20 | } 21 | 22 | public boolean containsPerson(Person p) { 23 | return safeMySet.contains(p); 24 | } 25 | } 26 | 27 | class Person { 28 | } 29 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/concurrent/chapter3/HiddenIterate.java: -------------------------------------------------------------------------------- 1 | package com.hit.concurrent.chapter3; 2 | 3 | import java.util.HashSet; 4 | import java.util.Random; 5 | import java.util.Set; 6 | 7 | /** 8 | * author:Charies Gavin 9 | * date:2018/11/17,10:46 10 | * https:github.com/guobinhit 11 | * description:隐藏迭代器 12 | */ 13 | public class HiddenIterate { 14 | private final Set set = new HashSet(); 15 | 16 | public synchronized void add(Integer i) { 17 | set.add(i); 18 | } 19 | 20 | public synchronized void remove(Integer i) { 21 | set.remove(i); 22 | } 23 | 24 | public void addTenThings() { 25 | Random random = new Random(); 26 | for (int i = 0; i < 10; i++) { 27 | add(random.nextInt()); 28 | } 29 | System.out.println("DEBUG: added ten elements to " + set); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter1/Finalizer.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter1; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/5/27,11:29 6 | * https:github.com/guobinhit 7 | * description:终结方法 8 | */ 9 | public class Finalizer { 10 | @Override 11 | protected void finalize() throws Throwable { 12 | try { 13 | // 终结子类状态 14 | } finally { 15 | super.finalize(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter1/Foo.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter1; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/5/27,11:35 6 | * https:github.com/guobinhit 7 | * description:终结方法守卫者 8 | */ 9 | public class Foo { 10 | /** 11 | * 终结方法守护者 12 | */ 13 | private final Object finalizerGuardian = new Object() { 14 | @Override 15 | protected void finalize() throws Throwable { 16 | // 终结外围类对象 17 | } 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter1/SimpleStack.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter1; 2 | 3 | import java.util.Arrays; 4 | import java.util.EmptyStackException; 5 | 6 | /** 7 | * author:Charies Gavin 8 | * date:2018/5/27,10:15 9 | * https:github.com/guobinhit 10 | * description:简单栈实现(含有内存泄漏危险) 11 | */ 12 | public class SimpleStack { 13 | private Object[] elements; 14 | private int size = 0; 15 | private static final int DEFAULT_INITIAL_CAPACITY = 16; 16 | 17 | public SimpleStack() { 18 | elements = new Object[DEFAULT_INITIAL_CAPACITY]; 19 | } 20 | 21 | /** 22 | * 压栈 23 | * 24 | * @param e 25 | */ 26 | public void push(Object e) { 27 | ensureCapacity(); 28 | elements[size++] = e; 29 | } 30 | 31 | /** 32 | * 弹栈 33 | * 34 | * @return 35 | */ 36 | public Object pop() { 37 | if (size == 0) { 38 | throw new EmptyStackException(); 39 | } else { 40 | Object result = elements[--size]; 41 | elements[size] = null; 42 | return result; 43 | 44 | // 如果仅返回 elements[--size],栈内部会维护着过期引用,有内存泄漏的风险 45 | // return elements[--size]; 46 | } 47 | } 48 | 49 | /** 50 | * 保证栈的容量,在必要时,进行自动扩容 51 | */ 52 | private void ensureCapacity() { 53 | if (elements.length == size) { 54 | elements = Arrays.copyOf(elements, 2 * size + 1); 55 | } 56 | } 57 | 58 | public static void main(String[] args) { 59 | SimpleStack simpleStack = new SimpleStack(); 60 | for (String string : "1,2,3,4,5,6".split(",")) { 61 | simpleStack.push(string); 62 | System.out.print(string + " "); 63 | } 64 | 65 | System.out.println(); 66 | 67 | while (simpleStack.size > 0) { 68 | System.out.print(simpleStack.pop() + " "); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter1/StaticFactory.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter1; 2 | 3 | import java.util.HashMap; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/5/23,20:50 8 | * https:github.com/guobinhit 9 | * description:静态工厂 10 | */ 11 | public class StaticFactory { 12 | public static Boolean valueOf(boolean b) { 13 | return b ? Boolean.TRUE : Boolean.FALSE; 14 | } 15 | 16 | public static HashMap newHashMap() { 17 | return new HashMap(); 18 | } 19 | 20 | public static void main(String[] args) { 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter1/UtilityClass.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter1; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/5/27,9:58 6 | * https:github.com/guobinhit 7 | * description:通过私有构造器强化不可实例化能力 8 | */ 9 | public class UtilityClass { 10 | /** 11 | * 私有化构造器,并在类内部无意识调用该构造器的时候,抛出错误 12 | */ 13 | private UtilityClass() { 14 | throw new AssertionError(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter1/init/NutritionFacts.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter1.init; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/5/24,8:30 6 | * https:github.com/guobinhit 7 | * description:重叠构造器模式 8 | */ 9 | public class NutritionFacts { 10 | // 必填项 11 | private final int servingSize; 12 | // 必填项 13 | private final int servings; 14 | // 选填项 15 | private final int calories; 16 | // 选填项 17 | private final int fat; 18 | // 选填项 19 | private final int sodium; 20 | // 选填项 21 | private final int carbohydrate; 22 | 23 | public NutritionFacts(int servingSize, int servings) { 24 | this(servingSize, servings, 0); 25 | } 26 | 27 | public NutritionFacts(int servingSize, int servings, int calories) { 28 | this(servingSize, servings, calories, 0); 29 | } 30 | 31 | public NutritionFacts(int servingSize, int servings, int calories, int fat) { 32 | this(servingSize, servings, calories, fat, 0); 33 | } 34 | 35 | public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium) { 36 | this(servingSize, servings, calories, fat, sodium, 0); 37 | } 38 | 39 | public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium, int carbohydrate) { 40 | this.servingSize = servingSize; 41 | this.servings = servings; 42 | this.calories = calories; 43 | this.fat = fat; 44 | this.sodium = sodium; 45 | this.carbohydrate = carbohydrate; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter1/init/NutritionFacts2.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter1.init; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/5/24,8:45 6 | * https:github.com/guobinhit 7 | * description:JavaBeans模式 8 | */ 9 | public class NutritionFacts2 { 10 | // 必填项 11 | private int servingSize = -1; 12 | // 必填项 13 | private int servings = -1; 14 | // 选填项 15 | private int calories = 0; 16 | // 选填项 17 | private int fat = 0; 18 | // 选填项 19 | private int sodium = 0; 20 | // 选填项 21 | private int carbohydrate = 0; 22 | 23 | public NutritionFacts2() { 24 | } 25 | 26 | public void setServingSize(int servingSize) { 27 | this.servingSize = servingSize; 28 | } 29 | 30 | public void setServings(int servings) { 31 | this.servings = servings; 32 | } 33 | 34 | public void setCalories(int calories) { 35 | this.calories = calories; 36 | } 37 | 38 | public void setFat(int fat) { 39 | this.fat = fat; 40 | } 41 | 42 | public void setSodium(int sodium) { 43 | this.sodium = sodium; 44 | } 45 | 46 | public void setCarbohydrate(int carbohydrate) { 47 | this.carbohydrate = carbohydrate; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter1/services/Provider.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter1.services; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/5/23,22:02 6 | * https:github.com/guobinhit 7 | * description:提供者接口 8 | */ 9 | public interface Provider { 10 | Service newService(); 11 | } 12 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter1/services/Service.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter1.services; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/5/23,21:00 6 | * https:github.com/guobinhit 7 | * description:服务接口 8 | */ 9 | public interface Service { 10 | } 11 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter1/services/ServiceProviderFramework.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter1.services; 2 | 3 | import java.util.Map; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | 6 | /** 7 | * author:Charies Gavin 8 | * date:2018/5/23,21:05 9 | * https:github.com/guobinhit 10 | * description:服务提供者框架 11 | */ 12 | public class ServiceProviderFramework { 13 | // 私有化构造器,防止实例化 14 | private ServiceProviderFramework() { 15 | } 16 | 17 | private static final Map providers = new ConcurrentHashMap(); 18 | 19 | private static final String DEFAULT_PROVIDER_NAME = ""; 20 | 21 | // 服务提供者的注册 API 22 | public static void registerDefaultProvider(Provider p) { 23 | providers.put(DEFAULT_PROVIDER_NAME, p); 24 | } 25 | 26 | public static void registerProvider(String name, Provider p) { 27 | providers.put(name, p); 28 | } 29 | 30 | public static Service newInstance() { 31 | return newInstance(DEFAULT_PROVIDER_NAME); 32 | } 33 | 34 | public static Service newInstance(String name) { 35 | Provider p = providers.get(name); 36 | if (p == null) { 37 | throw new IllegalArgumentException("No provider registerd with name: " + name); 38 | } 39 | return p.newService(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter1/singleton/Elvis.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter1.singleton; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/5/26,11:51 6 | * https:github.com/guobinhit 7 | * description:单例模式,提供公有静态 final 域成员 8 | */ 9 | public class Elvis { 10 | /** 11 | * 设置公有静态 final 域 12 | */ 13 | public static final Elvis INSTANCE = new Elvis(); 14 | 15 | /** 16 | * 私有化构造器 17 | */ 18 | private Elvis() { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter1/singleton/Elvis2.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter1.singleton; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/5/26,12:05 8 | * https:github.com/guobinhit 9 | * description:单例模式,提供公有静态工厂方法 10 | */ 11 | public class Elvis2 implements Serializable { 12 | 13 | private static final long serialVersionUID = 8894903144474616531L; 14 | 15 | private static final Elvis2 INSTANCE = new Elvis2(); 16 | 17 | /** 18 | * 私有化构造器 19 | */ 20 | private Elvis2() { 21 | } 22 | 23 | /** 24 | * 公有静态工厂 25 | */ 26 | public static Elvis2 getInstance() { 27 | return INSTANCE; 28 | } 29 | 30 | /** 31 | * 防止反序列化是生成假冒的实例 32 | */ 33 | private Object readResolve() { 34 | return INSTANCE; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter1/singleton/Elvis3.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter1.singleton; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/5/27,9:46 6 | * https:github.com/guobinhit 7 | * description:通过单个枚举元素,实现单例模式 8 | */ 9 | public enum Elvis3 { 10 | INSTANCE; 11 | } 12 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter10/StringList.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter10; 2 | 3 | import java.io.IOException; 4 | import java.io.ObjectInputStream; 5 | import java.io.ObjectOutputStream; 6 | import java.io.Serializable; 7 | 8 | /** 9 | * author:Charies Gavin 10 | * date:2018/6/23,10:33 11 | * https:github.com/guobinhit 12 | * description:transient 13 | */ 14 | public final class StringList implements Serializable { 15 | private transient int size = 0; 16 | private transient Entry head = null; 17 | 18 | private static class Entry { 19 | String data; 20 | Entry next; 21 | Entry previous; 22 | } 23 | 24 | public final void add(String s) { 25 | } 26 | 27 | private void writeObject(ObjectOutputStream s) throws IOException { 28 | s.defaultWriteObject(); 29 | s.writeInt(size); 30 | } 31 | 32 | private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { 33 | s.defaultReadObject(); 34 | int numElements = s.readInt(); 35 | 36 | for (int i = 0; i < numElements; i++) { 37 | add((String) s.readObject()); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter2/PhoneNumber.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter2; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * author:Charies Gavin 8 | * date:2018/6/23,11:20 9 | * https:github.com/guobinhit 10 | * description:override equals & hashCode 11 | */ 12 | public final class PhoneNumber { 13 | private final short areaCode; 14 | private final short prefix; 15 | private final short lineNubmer; 16 | 17 | /** 18 | * 构造函数 19 | * 20 | * @param areaCode 21 | * @param prefix 22 | * @param lineNumber 23 | */ 24 | public PhoneNumber(int areaCode, int prefix, int lineNumber) { 25 | rangeCheck(areaCode, 999, "area code"); 26 | rangeCheck(prefix, 999, "prefix"); 27 | rangeCheck(lineNumber, 9999, "line number"); 28 | this.areaCode = (short) areaCode; 29 | this.prefix = (short) prefix; 30 | this.lineNubmer = (short) lineNumber; 31 | } 32 | 33 | /** 34 | * 参数校验方法 35 | * 36 | * @param arg 37 | * @param max 38 | * @param name 39 | */ 40 | private static void rangeCheck(int arg, int max, String name) { 41 | if (arg < 0 || arg > max) { 42 | throw new IllegalArgumentException(name + " : " + arg); 43 | } 44 | } 45 | 46 | /** 47 | * 覆盖 equals 方法 48 | * 49 | * @param o 50 | * @return true or false 51 | */ 52 | @Override 53 | public boolean equals(Object o) { 54 | if (o == this) { 55 | return true; 56 | } 57 | if (!(o instanceof PhoneNumber)) { 58 | return false; 59 | } 60 | PhoneNumber pn = (PhoneNumber) o; 61 | return pn.lineNubmer == lineNubmer 62 | && pn.prefix == prefix 63 | && pn.areaCode == areaCode; 64 | } 65 | 66 | @Override 67 | public int hashCode() { 68 | int result = 1120; 69 | result = 31 * result + areaCode; 70 | result = 31 * result + prefix; 71 | result = 31 * result + lineNubmer; 72 | return result; 73 | } 74 | 75 | public static void main(String[] args) { 76 | Map amap = new HashMap(); 77 | amap.put(new PhoneNumber(010, 521, 1314), "Gavin"); 78 | 79 | System.out.println(amap.get(new PhoneNumber(010, 521, 1314))); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter3/PhysicalConstants.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter3; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/5/29,9:12 6 | * https:github.com/guobinhit 7 | * description:常量接口(不提倡这么使用) 8 | */ 9 | public interface PhysicalConstants { 10 | // Avogadro's number (1/mol) 11 | static final double AVOGADROS_NUMBER = 6.02214199e23; 12 | 13 | // Boltzmann constant (J/K) 14 | static final double BOLTZMANN_CONSTANT = 1.3806503e-23; 15 | 16 | // Mass of the electron (kg) 17 | static final double ELECTRON_MASS = 9.10938199e-31; 18 | } 19 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter3/SecurityConstants.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter3; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | /** 8 | * author:Charies Gavin 9 | * date:2018/5/28,8:54 10 | * https:github.com/guobinhit 11 | * description:常量数组 12 | */ 13 | public class SecurityConstants { 14 | 15 | private SecurityConstants() { 16 | } 17 | 18 | /** 19 | * 存在潜在的安全漏洞 20 | */ 21 | public static final String[] UNSECURITY_DEFAULT_VALUES = {"5", "2", "0"}; 22 | 23 | /** 24 | * 安全的定义方法 25 | */ 26 | private static final String[] SECURITY_DEFAULT_VALUES = {"5", "2", "0"}; 27 | 28 | /** 29 | * 提供一个不可变的列表 30 | */ 31 | public static final List SECURITY_DEFAULT_VALUES_LIST = 32 | Collections.unmodifiableList(Arrays.asList(SECURITY_DEFAULT_VALUES)); 33 | 34 | /** 35 | * 返回私有数组的一个备份 36 | * 37 | * @return 38 | */ 39 | public static final String[] values() { 40 | return SECURITY_DEFAULT_VALUES.clone(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter4/SimpleStackPECS.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter4; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/6/5,8:39 8 | * https:github.com/guobinhit 9 | * description:有限制通配符类型 10 | */ 11 | public class SimpleStackPECS { 12 | private Object[] elements; 13 | private int size = 0; 14 | private static final int DEFAULT_INITIAL_CAPACITY = 16; 15 | 16 | public SimpleStackPECS() { 17 | elements = new Object[DEFAULT_INITIAL_CAPACITY]; 18 | } 19 | 20 | /** 21 | * 压栈 22 | * 23 | * @param e 24 | */ 25 | public void push(E e) { 26 | ensureCapacity(); 27 | elements[size++] = e; 28 | } 29 | 30 | /** 31 | * 弹栈 32 | * 33 | * @return 34 | */ 35 | public E pop() { 36 | if (size == 0) { 37 | throw new EmptyStackException(); 38 | } else { 39 | Object result = elements[--size]; 40 | elements[size] = null; 41 | return (E) result; 42 | } 43 | } 44 | 45 | /** 46 | * 保证栈的容量,在必要时,进行自动扩容 47 | */ 48 | private void ensureCapacity() { 49 | if (elements.length == size) { 50 | elements = Arrays.copyOf(elements, 2 * size + 1); 51 | } 52 | } 53 | 54 | /** 55 | * 判断栈内元素是否为空 56 | * 57 | * @return 58 | */ 59 | public boolean isEmpty() { 60 | if (size == 0) { 61 | return true; 62 | } else { 63 | return false; 64 | } 65 | } 66 | 67 | /** 68 | * 压栈,将参数中的所有元素压入栈 69 | * 70 | * @param src 71 | */ 72 | public void pushAll(Iterable src) { 73 | for (E e : src) { 74 | push(e); 75 | } 76 | } 77 | 78 | /** 79 | * 弹栈,将栈内所有原弹出栈,并添加到指定集合 80 | * 81 | * @param dst 82 | */ 83 | public void popAll(Collection dst) { 84 | while (!isEmpty()) { 85 | dst.add(pop()); 86 | } 87 | } 88 | 89 | public static void main(String[] args) { 90 | SimpleStackPECS simpleStack = new SimpleStackPECS(); 91 | 92 | List integerList = new ArrayList(); 93 | integerList.add(5); 94 | integerList.add(2); 95 | integerList.add(1); 96 | 97 | Iterable integers = integerList; 98 | 99 | simpleStack.pushAll(integers); 100 | 101 | Collection objects = new ArrayList(); 102 | 103 | simpleStack.popAll(objects); 104 | for (Object s : objects) { 105 | System.out.println(s); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter5/annotation/ExceptionTest.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter5.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * author:Charies Gavin 10 | * date:2018/6/8,8:32 11 | * https:github.com/guobinhit 12 | * description:自定义ExceptionTest注解 13 | */ 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target(ElementType.METHOD) 16 | public @interface ExceptionTest { 17 | Class value(); 18 | } 19 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter5/annotation/MoreExceptionTest.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter5.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * author:Charies Gavin 10 | * date:2018/6/8,8:43 11 | * https:github.com/guobinhit 12 | * description:自定义MoreExceptionTest注解 13 | */ 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target(ElementType.METHOD) 16 | public @interface MoreExceptionTest { 17 | Class[] value(); 18 | } 19 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter5/annotation/RunExceptionTests.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter5.annotation; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | 6 | /** 7 | * author:Charies Gavin 8 | * date:2018/6/8,8:33 9 | * https:github.com/guobinhit 10 | * description:测试ExceptionTest注解 11 | */ 12 | public class RunExceptionTests { 13 | /** 14 | * 该方法为抛出 ArithmeticException 异常,因此可以通过 @ExceptionTest 测试 15 | */ 16 | @ExceptionTest(ArithmeticException.class) 17 | public static void testAnnocation() { 18 | int i = 0; 19 | i = i / i; 20 | } 21 | 22 | /** 23 | * 该方法抛出 ArrayIndexOutOfBoundsException 异常,因此不可以通过 @ExceptionTest 测试 24 | */ 25 | @ExceptionTest(ArithmeticException.class) 26 | public static void testAnnocation2() { 27 | int[] a = new int[0]; 28 | int i = a[1]; 29 | } 30 | 31 | /** 32 | * 该方法没有抛出异常,因此不可以通过 @ExceptionTest 测试 33 | */ 34 | @ExceptionTest(ArithmeticException.class) 35 | public static void testAnnocation3() { 36 | } 37 | 38 | public static void main(String[] args) throws Exception { 39 | int tests = 0; 40 | int passed = 0; 41 | Class testClass = Class.forName("com.hit.effective.chapter5.annotation.RunExceptionTests"); 42 | // Class testClass = Class.forName(args[0]); 43 | for (Method method : testClass.getDeclaredMethods()) { 44 | // 判断类中的被 @Test 注解的方法 45 | if (method.isAnnotationPresent(ExceptionTest.class)) { 46 | tests++; 47 | try { 48 | // 通过反射,执行被注解的方法 49 | method.invoke(null); 50 | passed++; 51 | } catch (InvocationTargetException warppedExc) { 52 | Throwable exc = warppedExc.getCause(); 53 | Class excType = method.getAnnotation(ExceptionTest.class).value(); 54 | if (excType.isInstance(exc)) { 55 | passed++; 56 | } else { 57 | System.out.printf("Test %s failed: expected %s, got %s%n", method, excType.getName(), exc); 58 | 59 | } 60 | } catch (Exception exc) { 61 | System.out.println("Invalid @Test: " + method); 62 | } 63 | } 64 | } 65 | System.out.printf("Passed: %d, Failed: %d%n", passed, tests - passed); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter5/annotation/RunMoreExceptionTests.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter5.annotation; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * author:Charies Gavin 10 | * date:2018/6/8,8:45 11 | * https:github.com/guobinhit 12 | * description:测试MoreExceptionTest注解 13 | */ 14 | public class RunMoreExceptionTests { 15 | /** 16 | * 该方法为抛出 ArithmeticException 异常,因此可以通过 @ExceptionTest 测试 17 | */ 18 | @MoreExceptionTest({IndexOutOfBoundsException.class, NullPointerException.class}) 19 | public static void testAnnocation() { 20 | List list = new ArrayList(); 21 | list.add(5, null); 22 | } 23 | 24 | 25 | public static void main(String[] args) throws Exception { 26 | int tests = 0; 27 | int passed = 0; 28 | Class testClass = Class.forName("com.hit.effective.chapter5.annotation.RunMoreExceptionTests"); 29 | // Class testClass = Class.forName(args[0]); 30 | for (Method method : testClass.getDeclaredMethods()) { 31 | // 判断类中的被 @Test 注解的方法 32 | if (method.isAnnotationPresent(MoreExceptionTest.class)) { 33 | tests++; 34 | try { 35 | // 通过反射,执行被注解的方法 36 | method.invoke(null); 37 | System.out.printf("Test %s failed: no exception%n", method); 38 | } catch (InvocationTargetException warppedExc) { 39 | Throwable exc = warppedExc.getCause(); 40 | Class[] excTypes = method.getAnnotation(MoreExceptionTest.class).value(); 41 | int oldPassed = passed; 42 | for (Class excType : excTypes) { 43 | if (excType.isInstance(exc)) { 44 | passed++; 45 | break; 46 | } 47 | } 48 | if (passed == oldPassed) { 49 | System.out.printf("Test %s failed: %s %n", method, exc); 50 | } 51 | 52 | } catch (Exception exc) { 53 | System.out.println("Invalid @Test: " + method); 54 | } 55 | } 56 | } 57 | System.out.printf("Passed: %d, Failed: %d%n", passed, tests - passed); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter5/annotation/RunTests.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter5.annotation; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | 6 | /** 7 | * author:Charies Gavin 8 | * date:2018/6/8,8:08 9 | * https:github.com/guobinhit 10 | * description:测试Test注解 11 | */ 12 | public class RunTests { 13 | /** 14 | * 该方法为 静态无参 的,因此可以通过 @Test 测试 15 | */ 16 | @Test 17 | public static void testAnnocation() { 18 | System.out.println("hello world"); 19 | } 20 | 21 | /** 22 | * 该方法为 静态有参 的,因此不可以通过 @Test 测试 23 | */ 24 | @Test 25 | public static void testAnnocation2(String word) { 26 | System.out.println(word); 27 | } 28 | 29 | /** 30 | * 该方法为 非静态无参 的,因此不可以通过 @Test 测试 31 | */ 32 | @Test 33 | public void testAnnocation3() { 34 | System.out.println("hello world"); 35 | } 36 | 37 | public static void main(String[] args) throws Exception { 38 | int tests = 0; 39 | int passed = 0; 40 | Class testClass = Class.forName("com.hit.effective.chapter5.annotation.RunTests"); 41 | // Class testClass = Class.forName(args[0]); 42 | for (Method method : testClass.getDeclaredMethods()) { 43 | // 判断类中的被 @Test 注解的方法 44 | if (method.isAnnotationPresent(Test.class)) { 45 | tests++; 46 | try { 47 | // 通过反射,执行被注解的方法 48 | method.invoke(null); 49 | passed++; 50 | } catch (InvocationTargetException warppedExc) { 51 | Throwable exc = warppedExc.getCause(); 52 | System.out.println(method + " failed: " + exc); 53 | } catch (Exception exc) { 54 | System.out.println("Invalid @Test: " + method); 55 | } 56 | } 57 | } 58 | System.out.printf("Passed: %d, Failed: %d%n", passed, tests - passed); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter5/annotation/Test.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter5.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * author:Charies Gavin 10 | * date:2018/6/7,8:47 11 | * https:github.com/guobinhit 12 | * description:Test注解 13 | */ 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target(ElementType.METHOD) 16 | public @interface Test { 17 | } 18 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter5/enums/IntEnum.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter5.enums; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/6/6,8:30 6 | * https:github.com/guobinhit 7 | * description:常量枚举模式 8 | */ 9 | public class IntEnum { 10 | public static final int MAN = 0; 11 | public static final int WOMAN = 1; 12 | } 13 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter5/enums/Operation.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter5.enums; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/6/6,9:11 6 | * https:github.com/guobinhit 7 | * description:特定于常量的方法 8 | */ 9 | public enum Operation { 10 | PLUS("+") { 11 | @Override 12 | double apply(double x, double y) { 13 | return x + y; 14 | } 15 | }, 16 | MINUS("-") { 17 | @Override 18 | double apply(double x, double y) { 19 | return x - y; 20 | } 21 | }, 22 | TIMES("*") { 23 | @Override 24 | double apply(double x, double y) { 25 | return x * y; 26 | } 27 | }, 28 | DIVIDE("/") { 29 | @Override 30 | double apply(double x, double y) { 31 | return x / y; 32 | } 33 | }; 34 | 35 | private final String symbol; 36 | 37 | Operation(String symbol) { 38 | this.symbol = symbol; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return symbol; 44 | } 45 | 46 | abstract double apply(double x, double y); 47 | 48 | /** 49 | * 实现反运算 50 | * 51 | * @param op 52 | * @return 53 | */ 54 | private static Operation inverse(Operation op) { 55 | switch (op) { 56 | case PLUS: 57 | return Operation.MINUS; 58 | case MINUS: 59 | return Operation.PLUS; 60 | case TIMES: 61 | return Operation.DIVIDE; 62 | case DIVIDE: 63 | return Operation.TIMES; 64 | default: 65 | throw new AssertionError("Unknown op: " + op); 66 | } 67 | } 68 | 69 | public static void main(String[] args) { 70 | double x = 10000; 71 | double y = 5; 72 | 73 | for (Operation op : Operation.values()) { 74 | System.out.printf("%f %s %f = %f%n", x, op, y, op.apply(x, y)); 75 | System.out.printf("%f %s %f = %f%n", x, op, y, inverse(op).apply(x, y)); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter5/enums/Orange.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter5.enums; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/6/6,8:36 6 | * https:github.com/guobinhit 7 | * description:枚举类型 8 | */ 9 | public enum Orange { 10 | NAVEL, 11 | TEMOLE, 12 | BLOOD 13 | } 14 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter5/enums/PayrollDay.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter5.enums; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/6/7,8:20 6 | * https:github.com/guobinhit 7 | * description:策略枚举应用示例 8 | */ 9 | public enum PayrollDay { 10 | MONDAY(PayType.WEEKDAY), TUESDAY(PayType.WEEKDAY), WEDNESDAY(PayType.WEEKDAY), 11 | THURSDAY(PayType.WEEKDAY), FRIDAY(PayType.WEEKDAY), SATURADY(PayType.WEEKEND), SUNDAY(PayType.WEEKEND); 12 | 13 | private final PayType payType; 14 | 15 | PayrollDay(PayType payType) { 16 | this.payType = payType; 17 | } 18 | 19 | // 调用策略枚举中的方法,计算工资 20 | double pay(double hoursWorked, double payRate) { 21 | return payType.pay(hoursWorked, payRate); 22 | } 23 | 24 | // 策略枚举 25 | private enum PayType { 26 | WEEKDAY { 27 | @Override 28 | double overtimePay(double hours, double payRate) { 29 | return hours <= HOURS_PER_SHIFT ? 0 : 30 | (hours - HOURS_PER_SHIFT) * payRate / 2; 31 | } 32 | }, 33 | WEEKEND { 34 | @Override 35 | double overtimePay(double hours, double payRate) { 36 | return hours * payRate / 2; 37 | } 38 | }; 39 | 40 | private static final int HOURS_PER_SHIFT = 8; 41 | 42 | // 强制策略枚举中的每个枚举都覆盖此方法 43 | abstract double overtimePay(double hours, double payRate); 44 | 45 | // 实际计算工资的方法 46 | double pay(double hoursWorked, double payRate) { 47 | double basePay = hoursWorked * payRate; 48 | return basePay + overtimePay(hoursWorked, payRate); 49 | } 50 | } 51 | 52 | public static void main(String[] args) { 53 | System.out.println(PayrollDay.MONDAY.pay(12, 100)); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter5/enums/Planet.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter5.enums; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/6/6,8:44 6 | * https:github.com/guobinhit 7 | * description:枚举类型中定义常量域 8 | */ 9 | public enum Planet { 10 | MERCURY(3.302e+23, 2.439e6), 11 | VENUS(4.869e+24, 6.052e6), 12 | EARTH(5.975e+23, 6.378e6), 13 | MARS(6.419e+23, 3.393e6), 14 | JUPITER(1.899e+27, 7.149e7), 15 | SATURN(5.685e+26, 6.027e7), 16 | URANUS(8.683e+25, 2.556e7), 17 | NEPTUNE(1.024e+26, 2.477e7); 18 | 19 | // In kilograms 20 | private final double mass; 21 | // In meters 22 | private final double radius; 23 | // In m / s^2 24 | private final double surfaceGravity; 25 | 26 | // Universal gravitational constant in m^3 / kg s^2 27 | private static final double G = 6.67300E-11; 28 | 29 | // constructor 30 | Planet(double mass, double radius) { 31 | this.mass = mass; 32 | this.radius = radius; 33 | surfaceGravity = G * mass / (radius * radius); 34 | } 35 | 36 | public double getMass() { 37 | return mass; 38 | } 39 | 40 | public double getRadius() { 41 | return radius; 42 | } 43 | 44 | public double getSurfaceGravity() { 45 | return surfaceGravity; 46 | } 47 | 48 | public double surfaceWeight(double mass) { 49 | // F = ma 50 | return mass * surfaceGravity; 51 | } 52 | 53 | public static void main(String[] args) { 54 | System.out.println(EARTH.getMass()); 55 | System.out.println(EARTH.getRadius()); 56 | System.out.println(EARTH.getSurfaceGravity()); 57 | System.out.println(EARTH.surfaceWeight(EARTH.getMass())); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter6/CollectionClassifier.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter6; 2 | 3 | import java.math.BigInteger; 4 | import java.util.*; 5 | 6 | /** 7 | * author:Charies Gavin 8 | * date:2018/6/9,10:52 9 | * https:github.com/guobinhit 10 | * description:重载方法 11 | */ 12 | public class CollectionClassifier { 13 | public static String classify(Set set) { 14 | return "Set"; 15 | } 16 | 17 | public static String classify(List list) { 18 | return "list"; 19 | } 20 | 21 | public static String classify(Collection collection) { 22 | return "Unknown Collection"; 23 | } 24 | 25 | public static void main(String[] args) { 26 | Collection[] collections = { 27 | new HashSet(), 28 | new ArrayList(), 29 | new HashMap().values() 30 | }; 31 | 32 | /** 33 | * 因为重载方法的选择是静态的,是在编译时选择的, 34 | * 因此都执行了 classify(Collection collection) 方法 35 | */ 36 | for (Collection collection : collections) { 37 | System.out.println(classify(collection)); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter6/Period.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter6; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/6/9,9:48 8 | * https:github.com/guobinhit 9 | * description:保护性拷贝 10 | */ 11 | public final class Period { 12 | private final Date start; 13 | private final Date end; 14 | 15 | /** 16 | * 未使用保护性拷贝的构造器 17 | * 18 | * @param start 19 | * @param end 20 | */ 21 | // public Period(Date start, Date end) { 22 | // if (start.compareTo(end) > 0) 23 | // throw new IllegalArgumentException(start + "after " + end); 24 | // this.start = start; 25 | // this.end = end; 26 | // } 27 | 28 | /** 29 | * 使用保护性拷贝的构造器 30 | * 31 | * @param start 32 | * @param end 33 | */ 34 | public Period(Date start, Date end) { 35 | this.start = new Date(start.getTime()); 36 | this.end = new Date(end.getTime()); 37 | 38 | if (this.start.compareTo(this.end) > 0) 39 | throw new IllegalArgumentException(start + "after " + end); 40 | } 41 | 42 | public Date start() { 43 | return new Date(start.getTime()); 44 | } 45 | 46 | public Date end() { 47 | return new Date(end.getTime()); 48 | } 49 | 50 | public static void main(String[] args) { 51 | Date start = new Date(); 52 | Date end = new Date(); 53 | 54 | Period period = new Period(start, end); 55 | System.out.println("Period: start = " + period.start + ", end = " + period.end); 56 | 57 | period.end().setYear(78); 58 | System.out.println("Period: start = " + period.start + ", end = " + period.end); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter6/UseAssertion.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter6; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/6/8,9:10 6 | * https:github.com/guobinhit 7 | * description:使用断言校验参数的有效性 8 | */ 9 | public class UseAssertion { 10 | 11 | public static void main(String[] args) { 12 | int[] array = {3, -2, 1, -1, 0, 2, -3}; 13 | System.out.println("Before sort:"); 14 | printArray(array); 15 | 16 | bubbleSort(null); 17 | 18 | System.out.println("After sort:"); 19 | printArray(array); 20 | } 21 | 22 | /** 23 | * 冒泡排序 24 | * 25 | * @param array 26 | */ 27 | private static void bubbleSort(int[] array) { 28 | // 使用断言 29 | assert array != null; 30 | 31 | // 冒泡排序核心算法 32 | for (int i = array.length - 1; i > 0; i--) { 33 | for (int j = 0; j < i; j++) { 34 | if (array[j] > array[j + 1]) { 35 | int temp = array[j]; 36 | array[j] = array[j + 1]; 37 | array[j + 1] = temp; 38 | } 39 | } 40 | } 41 | } 42 | 43 | // 打印数组的便利方法 44 | public static void printArray(int[] arr) { 45 | System.out.print("{"); 46 | for (int i = 0; i < arr.length; i++) { 47 | System.out.print(arr[i]); 48 | if (i < arr.length - 1) { 49 | System.out.print(", "); 50 | } 51 | } 52 | System.out.println("}"); 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter6/VarargsMethod.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter6; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/6/9,11:11 6 | * https:github.com/guobinhit 7 | * description:可变参数 8 | */ 9 | public class VarargsMethod { 10 | public static int sum(int... args) { 11 | int sum = 0; 12 | for (int arg : args) { 13 | sum += arg; 14 | } 15 | return sum; 16 | } 17 | 18 | public static int min(int firstArg, int... remainingArgs) { 19 | int min = firstArg; 20 | for (int arg : remainingArgs) { 21 | if (arg < min) { 22 | min = arg; 23 | } 24 | } 25 | return min; 26 | } 27 | 28 | public static void main(String[] args) { 29 | System.out.println(sum(1, 2, 3, 4, 5)); 30 | 31 | System.out.println(min(0, 1, 2, 3, -1)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter7/ForEachCircle.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter7; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collection; 5 | import java.util.Iterator; 6 | 7 | /** 8 | * author:Charies Gavin 9 | * date:2018/6/11,8:47 10 | * https:github.com/guobinhit 11 | * description:For-each循环 12 | */ 13 | public class ForEachCircle { 14 | enum Face {ONE, TWO, THREE, FOUR, FIVE, SIX} 15 | 16 | public static void main(String[] args) { 17 | Collection faces = Arrays.asList(Face.values()); 18 | 19 | // 包含一个BUG 20 | for (Iterator i = faces.iterator(); i.hasNext(); ) { 21 | for (Iterator j = faces.iterator(); j.hasNext(); ) { 22 | System.out.println(i.next() + " " + j.next()); 23 | } 24 | } 25 | 26 | System.out.println("+++ 上面有Bug,下面为修复版 1 +++"); 27 | 28 | // 修复版 1 29 | for (Iterator i = faces.iterator(); i.hasNext(); ) { 30 | Face tempFace = i.next(); 31 | for (Iterator j = faces.iterator(); j.hasNext(); ) { 32 | System.out.println(tempFace + " " + j.next()); 33 | } 34 | } 35 | 36 | System.out.println("+++ 下面为修复版 2 +++"); 37 | 38 | // 修复版 2 39 | for (Face face1 : faces) { 40 | for (Face face2 : faces) { 41 | System.out.println(face1 + " " + face2); 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter7/WhileCircle.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter7; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Iterator; 5 | import java.util.List; 6 | 7 | /** 8 | * author:Charies Gavin 9 | * date:2018/6/11,8:33 10 | * https:github.com/guobinhit 11 | * description:While循环 12 | */ 13 | public class WhileCircle { 14 | public static void main(String[] args) { 15 | List list = new ArrayList(); 16 | List list2 = new ArrayList(); 17 | 18 | Iterator it = list.iterator(); 19 | while (it.hasNext()) { 20 | System.out.println("列表一中的元素:" + it.next()); 21 | } 22 | 23 | // 以下循环包含一个BUG 24 | Iterator it2 = list2.iterator(); 25 | while (it.hasNext()) { 26 | System.out.println("列表二中的元素:" + it.next()); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter8/CastException.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter8; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/6/12,9:10 6 | * https:github.com/guobinhit 7 | * description:异常转译及异常链 8 | */ 9 | public class CastException { 10 | public static void main(String[] args) { 11 | try { 12 | // Use lower-level abstraction to do our biding 13 | } catch (LowerLevelException e) { 14 | // throw higher-level exception 15 | throw new HigherLevelException(e); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter8/HigherLevelException.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter8; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/6/12,9:08 6 | * https:github.com/guobinhit 7 | * description:模拟高层异常 8 | */ 9 | public class HigherLevelException extends RuntimeException { 10 | public HigherLevelException() { 11 | super(); 12 | } 13 | 14 | public HigherLevelException(LowerLevelException e) { 15 | super(e); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter8/LowerLevelException.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter8; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/6/12,9:07 6 | * https:github.com/guobinhit 7 | * description:模拟底层异常 8 | */ 9 | public class LowerLevelException extends RuntimeException { 10 | } 11 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter9/DoubleCheckIdiom.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter9; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/6/22,9:17 6 | * https:github.com/guobinhit 7 | * description:双重检查模式 8 | */ 9 | public class DoubleCheckIdiom { 10 | private class FieldType { 11 | } 12 | 13 | private volatile FieldType field; 14 | 15 | FieldType getField() { 16 | // 此语句是为了在 field 已经被初始化时,进行一次读取操作,用于提升性能 17 | FieldType result = field; 18 | // 第一次检查,无锁定 19 | if (result == null) { 20 | // 第二次检查,有锁定 21 | synchronized (this) { 22 | result = field; 23 | if (result == null) { 24 | field = result = new FieldType(); 25 | } 26 | } 27 | } 28 | return result; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter9/HolderClassIdiom.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter9; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/6/22,9:00 6 | * https:github.com/guobinhit 7 | * description:延迟初始化Holder类模式 8 | */ 9 | public class HolderClassIdiom { 10 | private static class FieldHolder { 11 | static final int field = computeFiledValue(); 12 | } 13 | 14 | static int getField() { 15 | return FieldHolder.field; 16 | } 17 | 18 | private static int computeFiledValue() { 19 | return 0; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter9/SingleCheckIdiom.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter9; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/6/22,9:31 6 | * https:github.com/guobinhit 7 | * description:单重检查模式 8 | */ 9 | public class SingleCheckIdiom { 10 | private class FieldType { 11 | } 12 | 13 | private volatile FieldType field; 14 | 15 | FieldType getField() { 16 | FieldType result = field; 17 | if (result == null) { 18 | field = result = new FieldType(); 19 | } 20 | return result; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter9/StopThread.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter9; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/6/21,7:59 8 | * https:github.com/guobinhit 9 | * description:线程示例1 10 | */ 11 | public class StopThread { 12 | private static boolean stopRequested; 13 | 14 | public static void main(String[] args) throws InterruptedException { 15 | Thread backgroundThread = new Thread(new Runnable() { 16 | @Override 17 | public void run() { 18 | int i = 0; 19 | while (!stopRequested) { 20 | i++; 21 | System.out.println("Thread running i = " + i); 22 | } 23 | } 24 | }); 25 | backgroundThread.start(); 26 | 27 | TimeUnit.SECONDS.sleep(1); 28 | stopRequested = true; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter9/StopThread2.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter9; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/6/21,8:13 8 | * https:github.com/guobinhit 9 | * description:线程示例2(需要将读和写操作都同步,否则同步不会起作用) 10 | */ 11 | public class StopThread2 { 12 | private static boolean stopRequested; 13 | 14 | private static synchronized void requestStop() { 15 | stopRequested = true; 16 | } 17 | 18 | private static synchronized boolean isStopRequested() { 19 | return stopRequested; 20 | } 21 | 22 | public static void main(String[] args) throws InterruptedException { 23 | Thread backgroundThread = new Thread(new Runnable() { 24 | @Override 25 | public void run() { 26 | int i = 0; 27 | while (!isStopRequested()) { 28 | i++; 29 | System.out.println("Thread running i = " + i); 30 | } 31 | } 32 | }); 33 | backgroundThread.start(); 34 | 35 | TimeUnit.SECONDS.sleep(1); 36 | requestStop(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter9/StopThread3.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter9; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/6/21,8:26 8 | * https:github.com/guobinhit 9 | * description:线程示例3 10 | */ 11 | public class StopThread3 { 12 | private static volatile boolean stopRequested; 13 | 14 | public static void main(String[] args) throws InterruptedException { 15 | Thread backgroundThread = new Thread(new Runnable() { 16 | @Override 17 | public void run() { 18 | int i = 0; 19 | while (!stopRequested) { 20 | i++; 21 | System.out.println("Thread running i = " + i); 22 | } 23 | } 24 | }); 25 | backgroundThread.start(); 26 | 27 | TimeUnit.SECONDS.sleep(1); 28 | stopRequested = true; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/effective/chapter9/VolatileCase.java: -------------------------------------------------------------------------------- 1 | package com.hit.effective.chapter9; 2 | 3 | import java.util.concurrent.atomic.AtomicLong; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/6/21,8:31 8 | * https:github.com/guobinhit 9 | * description:Volatile操作符示例 10 | */ 11 | public class VolatileCase { 12 | private static volatile int nextSerialNumber = 0; 13 | 14 | private static final AtomicLong nextSerialNumber2 = new AtomicLong(); 15 | 16 | /** 17 | * 没有同步 18 | * 19 | * @return 20 | */ 21 | // public static int getNextSerialNumber() { 22 | // return nextSerialNumber++; 23 | // } 24 | public static synchronized int getNextSerialNumber() { 25 | return nextSerialNumber++; 26 | } 27 | 28 | public static long getNextSerialNumber2() { 29 | return nextSerialNumber2.getAndIncrement(); 30 | } 31 | 32 | 33 | public static void main(String[] args) { 34 | Thread thread_1 = new Thread(new Runnable() { 35 | @Override 36 | public void run() { 37 | for (int i = 0; i < 1000; i++) { 38 | System.out.println(Thread.currentThread() + " 序列号:" + getNextSerialNumber()); 39 | } 40 | } 41 | }); 42 | 43 | Thread thread_2 = new Thread(new Runnable() { 44 | @Override 45 | public void run() { 46 | for (int i = 0; i < 1000; i++) { 47 | System.out.println(Thread.currentThread() + " 序列号:" + getNextSerialNumber()); 48 | } 49 | } 50 | }); 51 | 52 | thread_1.start(); 53 | thread_2.start(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter1/LanguageGuide.md: -------------------------------------------------------------------------------- 1 | > **Java 发展史** 2 | 3 | Java 是一门面向对象的编程语言,它不仅吸收了 C++ 语言的各种优点,还摒弃了 C++ 里难以理解的多重继承、指针等概念,因此 Java 语言具有功能强大和简单易用两个特征。此外,Java 还具有简单性、面向对象、分布式、健壮性、安全性、平台独立与可移植性、多线程、动态性等特点。Java 语言作为静态面向对象编程语言的代表,极好地实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程。 4 | 5 | Java 语言缘起于 1991 年 Sun 成立的一个名为 Green 的项目小组,这个由詹姆斯·高斯林、帕特里克、麦克·舍林丹和其他几个工程师一起组成的工作小组在加利福尼亚州门洛帕克市沙丘路的一个小工作室里面研究开发新技术,专攻计算机在家电产品上的嵌入式应用,而这个小组的新技术成果就是 Java 语言的前身,名为 Oak 的面向对象编程语言。 6 | 7 | 虽然 Oak 是一门不错的面向对象编程语言,但是在随后的几年内,Oak 并没有受到市场的青睐。直到 1995 年,互联网的蓬勃发展给了 Oak 机会,Sun 公司首先推出了基于 Oak 的可以嵌入网页并且可以随同网页在网络上传输的 Applet(一种将小程序嵌入到网页中进行执行的技术),并于同年 5 月将 Oak 更名为 Java,这里还有一个小插曲,在申请注册商标时,由于发现 Oak 已经被人使用了,再想了一系列名字之后,最终,使用了提议者在喝一杯 Java 咖啡时无意提到的 Java 词语,Java 语言就此正式诞生。 8 | 9 | 自 1991 年 1 月 Sun 公司发布 Java 第一个开发工具包(JDK 1.0)至 2017 年 9 月 Oracle 发布 Java SE 9.0 期间,Java 经历了众多的迭代与更新,其中变化最大的一次更新当属 2004 年 9 月 30 日,J2SE 1.5 发布,这是 Java 语言发展史上的又一里程碑(第一个里程碑为 1991 年 Sun 发布 JDK 1.0,它标志着 Java 成为了一种独立的开发工具)。为了表示该版本的重要性,J2SE 1.5 更名为 Java SE 5.0(内部版本号 1.5.0),代号为 Tiger,Tiger 包含了从 1996 年发布 1.0 版本以来的最重大的更新,其中包括泛型、基本类型的自动装箱、改进的循环、枚举类型、注解、格式化 I/O 及可变参数等。 10 | 11 | > **面向对象** 12 | 13 | 亚里士多德大概是第一个深入研究类型的哲学家,他曾提出过鸟类和鱼类这样的概念。所有的对象都是唯一的,但是同时也是具有相同的特性和行为的对象所归属的类的一部分。在计算机语言的世界中,第一个面向对象的编程语言 Simula-67 就采用了上述的面向对象的思想,它在程序中使用关键字`class`来引入新的类型,Java 语言同样如此。 14 | 15 | 虽然 Simula-67 是第一个面向对象的编程语言,但它并不成功。第一个成功面向对象的语言是 Smalltalk ,同时它也是 Java 所基于的语言之一。Alan Kay(他是 Smalltalk 面向对象编程环境语言的发明人之一,也是面向对象编程思想的创始人之一,他还是笔记本电脑最早的构想者和现代 Windows GUI 的最初尝试者)曾总结了 Smalltalk 的五个基本特性,这些特性正是纯粹的面向对象的编程语言所该具有的,包括: 16 | 17 | - 万物皆对象; 18 | - 这是面向对象编程的终极奥义。 19 | - 程序是对象的集合,它们通过发生消息来告知彼此所要做的事情; 20 | - 简单点说,程序中包含不同的对象,对象之间通过调用方法(发送消息)来达到所要实现的具体行为。 21 | - 每个对象都有自己的由其他的对象所构成的存储; 22 | - 可以通过创建包含现有对象的方式来创建新的对象。 23 | - 每个对象都拥有其类型; 24 | - 每个对象都是某个类的实例,不同的类的区别是就可以接收不同的消息。 25 | - 某一特定类型的所有对象都可以接收同样的消息。 26 | - 如 Java 语言中的多态,导出类可以接收任何发给基类的消息。 27 | 28 | 在理想的面向对象的编程语言中,每个对象都有一个接口(并非绝对,例如我们单纯的想定义一个对象来表示某种类型体系,我们就可以不在对象里面定义接口,这里的接口指方法或者函数),我们通过发送消息(调用对象的接口)来告知对象我们要实现什么行为或者动作。反言之,每个对象都提供服务,我们通过想要实现的服务来确定给哪个对象发送消息。 29 | 30 | 相比于「非面向对象编程」的编译器产生的函数调用引起的所谓的「前期绑定」,即编译器产生一个对于具体函数名字的调用,而运行时将这个调用解析到将要执行的代码的绝对地址;「面向对象编程」最重要的地方就是:编译器不可能产生传统意义上的函数调用,而是使用了「后期绑定」的概念,即当向对象发送消息时,被调用的代码直到运行时才能确定。 31 | 32 | 除上述内容之外,Java 还提供了很多其他的特性来为我们编程做助力,例如单根(Object)继承体系、容器类、参数化类型(泛型)、高效的对象创建及生命周期(垃圾回收机制)、异常和错误处理、并发编程等。Java 的魅力,并不止于此! 33 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter10/FillException.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter10; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/10,16:50 6 | * https:github.com/guobinhit 7 | * description:重新抛出异常测试 8 | */ 9 | public class FillException { 10 | public static void main(String[] args) throws Exception { 11 | try { 12 | catchExceptionInitCause(); 13 | } catch (Exception e) { 14 | e.printStackTrace(); 15 | } 16 | } 17 | 18 | private static void newCatchException() throws Exception { 19 | try { 20 | getException(); 21 | } catch (Exception e) { 22 | System.out.println("Oh, catch a new exception"); 23 | // 通过 fillInStackTrace() 方法重新抛出异常 24 | throw (Exception) e.fillInStackTrace(); 25 | } 26 | } 27 | 28 | private static void catchException() throws Exception { 29 | try { 30 | getException(); 31 | } catch (Exception e) { 32 | System.out.println("Oh, catch a exception"); 33 | throw e; 34 | } 35 | } 36 | 37 | /** 38 | * 构造同一类型异常链使用构造器即可 39 | * 40 | * @throws Exception 41 | */ 42 | private static void catchExceptionStructure() throws Exception { 43 | try { 44 | getException(); 45 | } catch (Exception e) { 46 | System.out.println("Oh, catch a exception"); 47 | throw new Exception(e); 48 | } 49 | } 50 | 51 | /** 52 | * 构造非同一类型异常链需要使用 initCause() 方法 53 | * 54 | * @throws Exception 55 | */ 56 | private static void catchExceptionInitCause() throws Exception { 57 | try { 58 | getException(); 59 | } catch (Exception e) { 60 | System.out.println("Oh, catch a exception"); 61 | MyselfException myselfException = new MyselfException(); 62 | myselfException.initCause(e); 63 | throw myselfException; 64 | } 65 | } 66 | 67 | private static void getException() throws Exception { 68 | Exception exception = new Exception("Ops, cause a exception"); 69 | throw exception; 70 | } 71 | } -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter10/FinallyException.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter10; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/10,19:06 6 | * https:github.com/guobinhit 7 | * description:测试finally关键字 8 | */ 9 | public class FinallyException { 10 | public static void main(String[] args) throws Exception { 11 | // 循环调用 testFinally() 方法 12 | for (int i = 1; i < 5; i++) { 13 | testFinally(i); 14 | } 15 | } 16 | 17 | /** 18 | * 测试 finally 子句 19 | * 20 | * @param i 21 | * @throws Exception 22 | */ 23 | private static void testFinally(int i) throws Exception { 24 | try { 25 | System.out.println("Initial test finally..."); 26 | if (i == 1) { 27 | System.out.println("i = " + i); 28 | return; 29 | } 30 | if (i == 2) { 31 | System.out.println("i = " + i); 32 | return; 33 | } 34 | if (i == 3) { 35 | System.out.println("i = " + i); 36 | return; 37 | } 38 | Exception exception = new Exception("Ops, it's a exception!"); 39 | throw exception; 40 | } catch (Exception e) { 41 | System.out.println("Exception: " + e.getMessage()); 42 | } finally { 43 | System.out.println("Hey buddy, u come in finally block!"); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter10/MatchException.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter10; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/10,19:40 6 | * https:github.com/guobinhit 7 | * description:测试catch子句匹配异常的情况 8 | */ 9 | public class MatchException { 10 | public static void main(String[] args) throws Exception { 11 | 12 | /** 13 | * 基类异常可以匹配导出类异常,即可以通过基类异常 catch 住 14 | */ 15 | try { 16 | ComplicatedException ce = new ComplicatedException(); 17 | throw ce; 18 | } catch (SimplieException e) { 19 | System.out.println("Catch SimplieException"); 20 | } 21 | 22 | /** 23 | * 导出类异常不能匹配基类异常,即不可以通过导出类异常 catch 住 24 | */ 25 | try { 26 | SimplieException ce = new SimplieException(); 27 | throw ce; 28 | } catch (ComplicatedException e) { 29 | System.out.println("Catch ComplicatedException"); 30 | } 31 | 32 | /** 33 | * 先 catch 基类异常,再 catch 导出类异常 34 | */ 35 | // try { 36 | // ComplicatedException ce = new ComplicatedException(); 37 | // throw ce; 38 | // } catch (SimplieException e) { 39 | // System.out.println("Catch SimplieException"); 40 | // } catch (ComplicatedException e) { 41 | // System.out.println("Catch ComplicatedException"); 42 | // } 43 | } 44 | } 45 | 46 | class SimplieException extends Exception { 47 | } 48 | 49 | class ComplicatedException extends SimplieException { 50 | } 51 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter10/MyselfException.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter10; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/10,16:00 6 | * https:github.com/guobinhit 7 | * description:自定义异常 8 | */ 9 | public class MyselfException extends Exception { 10 | /** 11 | * 默认构造器 12 | */ 13 | MyselfException() { 14 | } 15 | 16 | /** 17 | * 含参构造器 18 | * 19 | * @param msg 20 | */ 21 | MyselfException(String msg) { 22 | super(msg); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter10/TestException.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter10; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/3/10,16:20 8 | * https:github.com/guobinhit 9 | * description:自定义异常测试 10 | */ 11 | public class TestException { 12 | /** 13 | * 抛出异常 14 | * 15 | * @throws MyselfException 16 | */ 17 | private static void throwExceptionMehtod() throws MyselfException { 18 | MyselfException me = new MyselfException("自定义异常"); 19 | throw me; 20 | } 21 | 22 | public static void main(String[] args) { 23 | try { 24 | throwExceptionMehtod(); 25 | } catch (MyselfException myselfException) { 26 | System.out.println("MyselfException: " + myselfException); 27 | System.out.println(Arrays.toString(myselfException.getStackTrace())); 28 | myselfException.printStackTrace(); 29 | } catch (Exception exception) { 30 | System.out.println("Exception: " + exception); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter10/TestRuntimException.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter10; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/10,17:40 6 | * https:github.com/guobinhit 7 | * description:运行时异常测试 8 | */ 9 | public class TestRuntimException { 10 | public static void main(String[] args) { 11 | catchRuntimeException(); 12 | } 13 | 14 | private static void catchRuntimeException() { 15 | getRuntimeException(); 16 | } 17 | 18 | /** 19 | * 创建运行时异常并抛出 20 | */ 21 | private static void getRuntimeException() { 22 | RuntimeException re = new RuntimeException(); 23 | throw re; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter11/ConnectionString.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter11; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/11,14:20 6 | * https:github.com/guobinhit 7 | * description:连接字符串测试 8 | */ 9 | public class ConnectionString { 10 | public static void main(String[] args) { 11 | String hello = "Hello"; 12 | String helloWorld = hello + "World"; 13 | System.out.println(helloWorld); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter11/ObjectRegularExpression.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter11; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | /** 7 | * author:Charies Gavin 8 | * date:2018/3/11,19:12 9 | * https:github.com/guobinhit 10 | * description:创建正则表达式对象 11 | */ 12 | public class ObjectRegularExpression { 13 | /** 14 | * 自定义编译期常量 15 | */ 16 | public static final String POEM = "If you were a teardrop in my eye,\n" + 17 | "For fear of losing you,\n" + 18 | "I would never cry.\n" + 19 | "And if the golden sun,\n" + 20 | "Should cease to shine its light,\n" + 21 | "Just one smile from you,\n" + 22 | "would make my whole world bright."; 23 | 24 | public static void main(String[] args) { 25 | // 定义正则表达式字符串,含义为:找出每行后三个单词 26 | String regex = "(?m)(\\S+)\\s+((\\S+)\\s+(\\S+))$"; 27 | // 编译正则表达式字符串,获取 Pattern 对象 28 | Pattern pattern = Pattern.compile(regex); 29 | // 调用 Pattern 对象的 matcher() 方法,获取 Matcher 对象 30 | Matcher matcher = pattern.matcher(POEM); 31 | // 使用 find() 查找多个匹配结果 32 | while (matcher.find()) { 33 | // groupCount() 方法返回该匹配器的模式中的分组数目,不包括第 0 组 34 | for (int i = 0; i <= matcher.groupCount() ; i++) { 35 | // group(i) 返回前一次匹配的第 0 组,即整个匹配 36 | System.out.println("[" + matcher.group(i) + "]"); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter11/RegularExpressionExample.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter11; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | /** 7 | * author:Charies Gavin 8 | * date:2018/3/11,16:30 9 | * https:github.com/guobinhit 10 | * description:正则表达式对象 11 | */ 12 | public class RegularExpressionExample { 13 | public static void main(String[] args) { 14 | obtainRegex(); 15 | // replaceRegex(); 16 | // splitRegex(); 17 | // matchRegex(); 18 | } 19 | 20 | /** 21 | * 获取 22 | */ 23 | public static void obtainRegex() { 24 | String str = "Hi girl, I like you!"; 25 | String regex = "\\b[a-z]{3}\\b"; 26 | 27 | // 将正则表达式封装成对象 28 | Pattern pattern = Pattern.compile(regex); 29 | 30 | // 使用 Matcher 对象的方法对字符串进行操作,为了获取三个字母组成的单词,可以用查找 find() 方法 31 | Matcher matcher = pattern.matcher(str); 32 | System.out.println(str); 33 | 34 | while (matcher.find()) { 35 | // 获取匹配的字符串子序列 36 | System.out.println(matcher.group()); 37 | } 38 | } 39 | 40 | /** 41 | * 替换 42 | */ 43 | public static void replaceRegex() { 44 | // 替换字符串中重叠的字母为单独一个字母 45 | String str = "Harbingggggongyedaxxxxxue"; 46 | str = str.replaceAll("(.)\\1+", "$1"); 47 | System.out.println(str); 48 | 49 | // 对手机号进行模糊处理 50 | String tel = "18800001234"; 51 | tel = tel.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"); 52 | System.out.println(tel); 53 | } 54 | 55 | /** 56 | * 分割 57 | */ 58 | public static void splitRegex() { 59 | // 以字符串中的重叠字母进行分割 60 | String str = "Harbiniiigongyejjjjdaxue"; 61 | String[] names = str.split("(.)\\1+"); 62 | 63 | for(String name : names){ 64 | System.out.println(name); 65 | } 66 | } 67 | 68 | /** 69 | * 匹配 70 | */ 71 | public static void matchRegex() { 72 | // 验证该手机号是否满足号码规则 73 | String tel = "18800005238"; 74 | String regex = "1[358]\\d{9}"; 75 | boolean b = tel.matches(regex); 76 | System.out.println(tel + " : " + b); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter11/StringRegularExpression.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter11; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/3/11,16:00 8 | * https:github.com/guobinhit 9 | * description:测试 String 类支持正则表达式的方法 10 | */ 11 | public class StringRegularExpression { 12 | public static void main(String[] args) { 13 | String str = "123_456_789"; 14 | // matches() 方法用于匹配字符串 15 | System.out.println("匹配字符串:" + str.matches("-?\\S+")); 16 | // split() 方法用于分割字符串 17 | System.out.println("分割字符串:" + Arrays.toString(str.split("_"))); 18 | // replace() 方法用于替换字符串 19 | System.out.println("替换字符串:" + str.replace("_", "$")); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter11/UnconsciousRecursion.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter11; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * author:Charies Gavin 8 | * date:2018/3/11,15:20 9 | * https:github.com/guobinhit 10 | * description:无意识递归调用 11 | */ 12 | public class UnconsciousRecursion { 13 | public static void main(String[] args) { 14 | List list = new ArrayList(); 15 | for (int i = 0; i < 5; i++) { 16 | UnconsciousRecursion ur = new UnconsciousRecursion(); 17 | list.add(ur); 18 | } 19 | System.out.println(list); 20 | } 21 | 22 | /** 23 | * 由 this 导致的递归调用 24 | */ 25 | @Override 26 | public String toString(){ 27 | return "UnconsciousRecursion address: " + this + "\n"; 28 | } 29 | 30 | /** 31 | * 获取对象的内存地址,应该用 super.toString() 方法而非 this 32 | */ 33 | // @Override 34 | // public String toString(){ 35 | // return "UnconsciousRecursion address: " + super.toString() + "\n"; 36 | // } 37 | } 38 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter12/CheckClass.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter12; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * author:Charies Gavin 8 | * date:2018/3/18,17:20 9 | * https:github.com/guobinhit 10 | * description:检查类类型 11 | */ 12 | public class CheckClass { 13 | public static void main(String[] args) { 14 | Letter a = new Letter("a"); 15 | Letter b = new Letter("b"); 16 | Letter c = new Letter("c"); 17 | 18 | // if (a instanceof Letter) { 19 | // a.printlnName(); 20 | // } 21 | // if (b instanceof Letter) { 22 | // b.printlnName(); 23 | // } 24 | // if (c instanceof Letter) { 25 | // c.printlnName(); 26 | // } 27 | 28 | List letters = new ArrayList(); 29 | 30 | letters.add(a); 31 | letters.add(b); 32 | letters.add(c); 33 | 34 | // 获取 Letter 类对象 35 | Class letterClass = Letter.class; 36 | 37 | // 循环 letters 列表 38 | for (Letter letter : letters) { 39 | // 动态测试对象类型 40 | if (letterClass.isInstance(letter)) { 41 | letter.printlnName(); 42 | } 43 | } 44 | } 45 | 46 | } 47 | 48 | class Letter { 49 | String name; 50 | 51 | public Letter(String name) { 52 | this.name = name; 53 | } 54 | 55 | public void printlnName() { 56 | System.out.println("This is a Letter class instance: " + name); 57 | } 58 | } -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter12/CompareClass.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter12; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/18,16:20 6 | * https:github.com/guobinhit 7 | * description:比较类类型 8 | */ 9 | public class CompareClass { 10 | public static void main(String[] args) { 11 | compareClass(new BaseClass()); 12 | System.out.println(); 13 | compareClass(new SubClass()); 14 | } 15 | 16 | public static void compareClass(Object o) { 17 | // 获取待测试类的类类型 18 | System.out.println("Testing o of type : " + o.getClass()); 19 | 20 | // 通过 instanceof 和 isInstance() 进行比较 21 | System.out.println("o instanceof BaseClass : " + (o instanceof BaseClass)); 22 | System.out.println("o instanceof SubClass : " + (o instanceof SubClass)); 23 | System.out.println("BaseClass.isInstance(o) : " + BaseClass.class.isInstance(o)); 24 | System.out.println("SubClass.isInstance(o) : " + SubClass.class.isInstance(o)); 25 | 26 | // 通过 == 和 equals 进行比较 27 | System.out.println("o.getClass() == BaseClass.class : " + (o.getClass() == BaseClass.class)); 28 | System.out.println("o.getClass() == SubClass.class : " + (o.getClass() == SubClass.class)); 29 | System.out.println("o.getClass.equals(BaseClass.class) : " + o.getClass().equals(BaseClass.class)); 30 | System.out.println("o.getClass.equals(SubClass.class) : " + o.getClass().equals(SubClass.class)); 31 | } 32 | } 33 | 34 | class BaseClass { 35 | } 36 | 37 | class SubClass extends BaseClass { 38 | } 39 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter12/DotClass.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter12; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/3/18,10:00 8 | * https:github.com/guobinhit 9 | * description:测试通过 .class 获取 Class 对象 10 | */ 11 | public class DotClass { 12 | public static Random random = new Random(); 13 | 14 | public static void main(String[] args) { 15 | 16 | // 使用 .class 获取 Class 对象,并不直接初始化 17 | Class initable = Initable.class; 18 | 19 | System.out.println("After creating Initable reference!"); 20 | 21 | System.out.println(Initable.staticFinal); 22 | 23 | System.out.println(Initable.staticFinal2); 24 | 25 | System.out.println(Initable2.staticNonFinal); 26 | 27 | Class initable3 = null; 28 | 29 | try { 30 | // 使用 forName() 方法获取 Class 对象,直接进行初始化 31 | initable3 = Class.forName("com.hit.thought.chapter12.Initable3"); 32 | } catch (ClassNotFoundException e) { 33 | System.out.println("Sorry, I don't get Initable3 class!"); 34 | } 35 | 36 | System.out.println("After creating Initable3 reference!"); 37 | 38 | System.out.println(Initable3.staticNonFinal); 39 | } 40 | } 41 | 42 | class Initable { 43 | // static final 常量,编译期常量 44 | static final int staticFinal = 20180202; 45 | 46 | // static final 常量,非编译期常量 47 | static final int staticFinal2 = DotClass.random.nextInt(100); 48 | 49 | static { 50 | System.out.println("Initialing Initable"); 51 | } 52 | } 53 | 54 | class Initable2 { 55 | // static 非 final 常量 56 | static int staticNonFinal = 20180218; 57 | 58 | static { 59 | System.out.println("Initialing Initable2"); 60 | } 61 | } 62 | 63 | class Initable3 { 64 | // static 非 final 常量 65 | static int staticNonFinal = 20180318; 66 | 67 | static { 68 | System.out.println("Initialing Initable3"); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter12/Interface.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter12; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/18,15:30 6 | * https:github.com/guobinhit 7 | * description:定义接口 8 | */ 9 | public interface Interface { 10 | void doSomething(); 11 | 12 | void somethingElse(String arg); 13 | } 14 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter12/LoadClass.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter12; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/17,18:00 6 | * https:github.com/guobinhit 7 | * description:测试类加载 8 | */ 9 | public class LoadClass { 10 | public static void main(String[] args) { 11 | System.out.println("Hello BeiJing!"); 12 | new ChaoYang(); 13 | 14 | try { 15 | // Class 类的静态 forName() 方法的参数为类的全限定名(包括包名)字符串 16 | Class.forName("com.hit.thought.chapter12.XiCheng"); 17 | } catch (ClassNotFoundException e) { 18 | System.out.println("Not Fund Class!"); 19 | } 20 | 21 | new DongCheng(); 22 | System.out.println("Bye BeiJing!"); 23 | } 24 | } 25 | 26 | class ChaoYang { 27 | static { 28 | System.out.println("CHAOYANG!"); 29 | } 30 | } 31 | 32 | class XiCheng { 33 | static { 34 | System.out.println("XICHENG!"); 35 | } 36 | } 37 | 38 | class DongCheng { 39 | static { 40 | System.out.println("DONGCHENG!"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter12/NewInstance.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter12; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/11,15:20 6 | * https:github.com/guobinhit 7 | * description:创建类实例 8 | */ 9 | public class NewInstance { 10 | public static void main(String[] args) { 11 | Class c = null; 12 | 13 | try { 14 | c = Class.forName("com.hit.thought.chapter12.Instance"); 15 | } catch (ClassNotFoundException e) { 16 | System.out.println("Sorry, this class isn't found!"); 17 | } 18 | 19 | Instance instance = null; 20 | try { 21 | // 使用 newInstance() 来创建类实例,则该类必须含有默认的构造器 22 | instance = (Instance) c.newInstance(); 23 | } catch (Exception e) { 24 | System.out.println("Get instance exception!"); 25 | } 26 | instance.helleInstance(); 27 | } 28 | } 29 | 30 | class Instance { 31 | 32 | /** 33 | * 放开默认构造器(无参构造器)的注释,则程序正常运行 34 | */ 35 | // public Instance() { 36 | // } 37 | 38 | /** 39 | * 非默认构造器 40 | * 41 | * @param name 42 | */ 43 | public Instance(String name) { 44 | System.out.printf("Instance name is: " + name); 45 | } 46 | 47 | public void helleInstance() { 48 | System.out.println("Hello instance!"); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter12/RealObject.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter12; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/18,15:30 6 | * https:github.com/guobinhit 7 | * description:实现接口 8 | */ 9 | public class RealObject implements Interface { 10 | 11 | @Override 12 | public void doSomething() { 13 | System.out.println("doSomething!"); 14 | } 15 | 16 | @Override 17 | public void somethingElse(String arg) { 18 | System.out.println("somethingElse " + arg); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter12/ShowMethods.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter12; 2 | 3 | import java.lang.reflect.Constructor; 4 | import java.lang.reflect.Method; 5 | import java.util.regex.Pattern; 6 | 7 | /** 8 | * author:Charies Gavin 9 | * date:2018/3/18,14:20 10 | * https:github.com/guobinhit 11 | * description:类方法提取器 12 | */ 13 | public class ShowMethods { 14 | private static String usage = 15 | "Usage:\n" + 16 | "ShowMethods qualified.class.name\n" + 17 | "To show all methods in class or:\n" + 18 | "ShowMethods qualified.class.name word\n" + 19 | "To search for methods involving 'word'"; 20 | 21 | private static Pattern pattern = Pattern.compile("\\w+\\."); 22 | 23 | public static void main(String[] args) { 24 | if (args.length < 1) { 25 | System.out.println(usage); 26 | System.exit(0); 27 | } 28 | 29 | int lines = 0; 30 | 31 | try { 32 | Class c = Class.forName(args[0]); 33 | Method[] methods = c.getMethods(); 34 | Constructor[] constructors = c.getConstructors(); 35 | if (args.length == 1) { 36 | for (Method method : methods) { 37 | System.out.println(pattern.matcher(method.toString()).replaceAll("")); 38 | } 39 | for (Constructor constructor : constructors) { 40 | System.out.println(pattern.matcher(constructor.toString()).replaceAll("")); 41 | } 42 | lines = methods.length + constructors.length; 43 | } else { 44 | for (Method method : methods) { 45 | if (method.toString().indexOf(args[1]) != -1) { 46 | System.out.println(pattern.matcher(method.toString()).replaceAll("")); 47 | lines++; 48 | } 49 | } 50 | for (Constructor constructor : constructors) { 51 | if (constructor.toString().indexOf(args[1]) != -1) { 52 | System.out.println(pattern.matcher(constructor.toString()).replaceAll("")); 53 | lines++; 54 | } 55 | } 56 | } 57 | } catch (ClassNotFoundException e) { 58 | System.out.println("No such class: " + e); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter12/SimpleDynamicProxy.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter12; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.lang.reflect.Method; 5 | import java.lang.reflect.Proxy; 6 | 7 | /** 8 | * author:Charies Gavin 9 | * date:2018/3/18,15:240 10 | * https:github.com/guobinhit 11 | * description:动态代理 12 | */ 13 | public class SimpleDynamicProxy { 14 | 15 | public static void main(String[] args) { 16 | RealObject realObject = new RealObject(); 17 | 18 | consumer(realObject); 19 | 20 | Interface proxy = (Interface) Proxy.newProxyInstance( 21 | // 被代理类的类加载器 22 | Interface.class.getClassLoader(), 23 | // 希望该代理实现的接口列表 24 | new Class[]{Interface.class}, 25 | // InvocationHandler 接口的实现类 26 | new DynamicProxyHandler(realObject)); 27 | 28 | consumer(proxy); 29 | } 30 | 31 | public static void consumer(Interface iface) { 32 | iface.doSomething(); 33 | iface.somethingElse("Ops!"); 34 | } 35 | 36 | } 37 | 38 | class DynamicProxyHandler implements InvocationHandler { 39 | private Object proxied; 40 | 41 | public DynamicProxyHandler(Object proxied) { 42 | this.proxied = proxied; 43 | } 44 | 45 | @Override 46 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 47 | System.out.println("---> proxy: " + proxy.getClass() + 48 | ", method: " + method + 49 | ", args: " + args); 50 | if (args != null) { 51 | for (Object arg : args) { 52 | System.out.println(" " + arg); 53 | } 54 | } 55 | return method.invoke(proxied, args); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter12/reflect/A.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter12.reflect; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/18,18:20 6 | * https:github.com/guobinhit 7 | * description:定义接口 8 | */ 9 | public interface A { 10 | void f(); 11 | } 12 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter12/reflect/B.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter12.reflect; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/18,18:20 6 | * https:github.com/guobinhit 7 | * description:实现接口 8 | */ 9 | public class B implements A { 10 | @Override 11 | public void f() { 12 | } 13 | 14 | public void g() { 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter12/reflect/C.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter12.reflect; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/18,18:20 6 | * https:github.com/guobinhit 7 | * description:实现接口 8 | */ 9 | public class C implements A { 10 | @Override 11 | public void f() { 12 | System.out.println("public C.f()"); 13 | } 14 | 15 | public void g() { 16 | System.out.println("public C.g()"); 17 | } 18 | 19 | void u() { 20 | System.out.println("package C.u()"); 21 | } 22 | 23 | protected void v() { 24 | System.out.println("protect C.v()"); 25 | } 26 | 27 | private void w() { 28 | System.out.println("private C.w()"); 29 | } 30 | 31 | public static A makeA() { 32 | return new C(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter13/ErasedTypeEquivalence.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter13; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/4/21,17:23 8 | * https:github.com/guobinhit 9 | * description:测试擦除的效果 10 | */ 11 | public class ErasedTypeEquivalence { 12 | public static void main(String[] args) { 13 | Class c1 = new ArrayList().getClass(); 14 | Class c2 = new ArrayList().getClass(); 15 | System.out.println("ArrayList == ArrayList : " + (c1 == c2)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter13/Fibonacci.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter13; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/19,9:15 6 | * https:github.com/guobinhit 7 | * description:斐波那契数列 8 | */ 9 | public class Fibonacci implements Generator { 10 | private int count = 0; 11 | 12 | @Override 13 | public Integer next() { 14 | return fin(count++); 15 | } 16 | 17 | private int fin(int n) { 18 | if (n < 2) { 19 | return 1; 20 | } else { 21 | return fin(n - 2) + fin(n - 1); 22 | } 23 | } 24 | 25 | public static void main(String[] args) { 26 | Fibonacci fibonacci = new Fibonacci(); 27 | for (int i = 0; i < 20; i++) { 28 | System.out.println(fibonacci.next() + " "); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter13/Generator.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter13; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/19,9:15 6 | * https:github.com/guobinhit 7 | * description:生成器接口 8 | */ 9 | public interface Generator { 10 | T next(); 11 | } 12 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter13/GenericHolder.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter13; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/20,8:30 6 | * https:github.com/guobinhit 7 | * description:泛型持有对象 8 | */ 9 | public class GenericHolder { 10 | private T obj; 11 | 12 | public T getObj() { 13 | return obj; 14 | } 15 | 16 | public void setObj(T obj) { 17 | this.obj = obj; 18 | } 19 | 20 | public static void main(String[] args) { 21 | GenericHolder holder = new GenericHolder(); 22 | holder.setObj("HelloWorld"); 23 | String s = holder.getObj(); 24 | System.out.println(s); 25 | // holder.setObj(521); 26 | // Integer i = (Integer) holder.getObj(); 27 | // System.out.println(i); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter13/GenericMethod.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter13; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/4/21,17:15 6 | * https:github.com/guobinhit 7 | * description:测试泛型方法 8 | */ 9 | public class GenericMethod { 10 | // 定义泛型方法,只需将泛型参数列表置于方法的返回值之前 11 | private void getParameterClassName(T t) { 12 | System.out.println(t.getClass().getName()); 13 | } 14 | 15 | public static void main(String[] args) { 16 | GenericMethod gm = new GenericMethod(); 17 | gm.getParameterClassName("zora"); 18 | gm.getParameterClassName(521); 19 | gm.getParameterClassName(new String[]{"love"}); 20 | 21 | // 显式地指明类型 22 | GenericMethod gm2 = new GenericMethod(); 23 | gm2.getParameterClassName("5211314"); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter13/GenericVarargs.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter13; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * author:Charies Gavin 8 | * date:2018/4/21,17:15 9 | * https:github.com/guobinhit 10 | * description:测试泛型方法和可变参数 11 | */ 12 | public class GenericVarargs { 13 | // 使用可变参数的泛型方法 14 | public static List makeList(T... args) { 15 | List list = new ArrayList(); 16 | for (T item : args) { 17 | list.add(item); 18 | } 19 | return list; 20 | } 21 | 22 | public static void main(String[] args) { 23 | List ls = makeList("Hello"); 24 | System.out.println(ls); 25 | ls = makeList("Hello", "World"); 26 | System.out.println(ls); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter13/LinkedStack.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter13; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/19,8:40 6 | * https:github.com/guobinhit 7 | * description:链式存储结构 8 | */ 9 | public class LinkedStack { 10 | // 内部类,用于存储及维护链式结构 11 | private static class Node { 12 | // 存储的值 13 | U item; 14 | 15 | // 存储下一个节点的元素 16 | Node next; 17 | 18 | /** 19 | * 默认构造器 20 | */ 21 | Node() { 22 | item = null; 23 | next = null; 24 | } 25 | 26 | /** 27 | * 含参构造器 28 | * 29 | * @param item 30 | * @param next 31 | */ 32 | Node(U item, Node next) { 33 | this.item = item; 34 | this.next = next; 35 | } 36 | 37 | // 判断栈中下一个元素是否为空 38 | boolean end() { 39 | return item == null && next == null; 40 | } 41 | } 42 | 43 | // 末端哨兵,用于监视末端元素 44 | private Node top = new Node(); 45 | 46 | // 压栈 47 | public void push(T item) { 48 | /** 49 | * top 的结构示例为 top>>> 50 | * 栈中元素的性质为"先入后出,后入先出",因此最后一个压栈的元素在最前面,也最先弹栈 51 | */ 52 | top = new Node(item, top); 53 | } 54 | 55 | // 弹栈 56 | public T pop() { 57 | // 弹栈元素为链式存储结构中的从前往后数第一个 item 元素 58 | T result = top.item; 59 | // 如果判断 top.end() 为 false,则说明栈中下一个元素非 null,因此末端哨兵下移 60 | if (!top.end()) { 61 | top = top.next; 62 | } 63 | return result; 64 | } 65 | 66 | public static void main(String[] args) { 67 | LinkedStack linkedStack = new LinkedStack(); 68 | for (String str : "If I were boy".split(" ")) { 69 | linkedStack.push(str); 70 | } 71 | String s; 72 | while ((s = linkedStack.pop()) != null) { 73 | System.out.println(s); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter13/Manipulation.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter13; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/4/21,16:30 6 | * https:github.com/guobinhit 7 | * description:测试擦除的边界 8 | */ 9 | public class Manipulation { 10 | public static void main(String[] args) { 11 | Erased erased = new Erased(); 12 | 13 | Manipulator manipulator = new Manipulator(erased); 14 | manipulator.manipulator(); 15 | 16 | /** 17 | * 泛型类型参数将擦除到它的第一个边界,编译器实际上会把类型参数替换为它的擦除 18 | * 例如,Manipulator2 将擦除到 Erased 19 | */ 20 | Manipulator2 manipulator2 = new Manipulator2(erased); 21 | manipulator2.manipulator(); 22 | } 23 | } 24 | 25 | class Erased { 26 | public void erased() { 27 | System.out.println("Erased: erasing..."); 28 | } 29 | } 30 | 31 | class Erased2 { 32 | public void erased() { 33 | System.out.println("Erased2: erasing..."); 34 | } 35 | } 36 | 37 | class Manipulator { 38 | private T obj; 39 | 40 | public Manipulator(T t) { 41 | obj = t; 42 | } 43 | 44 | public void manipulator() { 45 | // obj.erased(); 46 | } 47 | } 48 | 49 | /** 50 | * 指定泛型边界 51 | * 52 | * @param 53 | */ 54 | class Manipulator2 { 55 | private T obj; 56 | 57 | public Manipulator2(T t) { 58 | obj = t; 59 | } 60 | 61 | public void manipulator() { 62 | obj.erased(); 63 | } 64 | } -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter13/SimpleHolder.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter13; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/20,8:30 6 | * https:github.com/guobinhit 7 | * description:简单持有对象 8 | */ 9 | public class SimpleHolder { 10 | private Object obj; 11 | 12 | public Object getObj() { 13 | return obj; 14 | } 15 | 16 | public void setObj(Object obj) { 17 | this.obj = obj; 18 | } 19 | 20 | public static void main(String[] args) { 21 | SimpleHolder holder = new SimpleHolder(); 22 | holder.setObj("HelloWorld"); 23 | String s = (String) holder.getObj(); 24 | System.out.println(s); 25 | holder.setObj(521); 26 | Integer i = (Integer) holder.getObj(); 27 | System.out.println(i); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter14/ArrayOptions.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter14; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/4/22,10:10 8 | * https:github.com/guobinhit 9 | * description:对象数组和基本类型数组 10 | */ 11 | public class ArrayOptions { 12 | public static void main(String[] args) { 13 | // 对象数组,三种初始化方式 14 | String[] strs = new String[10]; 15 | String[] strs2 = new String[]{"Z", "O", "R", "A"}; 16 | String[] strs3 = {"G", "A", "V", "I", "N"}; 17 | 18 | System.out.println("strs: " + Arrays.toString(strs)); 19 | System.out.println("strs2: " + Arrays.toString(strs2)); 20 | System.out.println("strs3: " + Arrays.toString(strs3)); 21 | 22 | strs = strs2; 23 | System.out.println("strs = strs2: " + Arrays.toString(strs)); 24 | 25 | strs[0] = "K"; 26 | System.out.println("strs & strs[0] = \"K\": " + Arrays.toString(strs)); 27 | System.out.println("strs2: " + Arrays.toString(strs2)); 28 | 29 | System.out.println("-------------------"); 30 | 31 | // 基本类型数组,三种初始化方式 32 | int[] ints = new int[10]; 33 | int[] ints2 = new int[]{1, 1, 2, 0}; 34 | int[] ints3 = {2, 0, 1, 5}; 35 | 36 | System.out.println("ints: " + Arrays.toString(ints) + " ints.length() = " + ints.length); 37 | System.out.println("ints2: " + Arrays.toString(ints2) + " ints2.length() = " + ints2.length); 38 | System.out.println("ints3: " + Arrays.toString(ints3) + " ints3.length() = " + ints3.length); 39 | 40 | for (int i = 0; i < ints2.length; i++) { 41 | ints[i] = ints2[i]; 42 | } 43 | 44 | // length() 表示数组的长度,而不是数组中实际保持元素的个数 45 | System.out.println("ints: " + Arrays.toString(ints) + " ints.length() = " + ints.length); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter14/ComparableImpl.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter14; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/4/22,10:30 6 | * https:github.com/guobinhit 7 | * description:实现Comparable接口 8 | */ 9 | public class ComparableImpl implements Comparable { 10 | 11 | int age; 12 | 13 | // 显示声明构造函数,强制必须传一个 int 类型的参数 14 | public ComparableImpl(int age) { 15 | this.age = age; 16 | } 17 | 18 | @Override 19 | public int compareTo(ComparableImpl comparable) { 20 | return age < comparable.age ? -1 : (age == comparable.age ? 0 : 1); 21 | } 22 | 23 | public static void main(String[] args) { 24 | ComparableImpl gavin = new ComparableImpl(28); 25 | ComparableImpl zora = new ComparableImpl(27); 26 | System.out.println(gavin.compareTo(zora)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter14/ComparatorImpl.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter14; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | 6 | /** 7 | * author:Charies Gavin 8 | * date:2018/4/22,10:45 9 | * https:github.com/guobinhit 10 | * description:实现Comparator接口 11 | */ 12 | public class ComparatorImpl implements Comparator { 13 | 14 | @Override 15 | public int compare(Person p1, Person p2) { 16 | return p1.age < p2.age ? -1 : (p1.age == p2.age ? 0 : 1); 17 | } 18 | 19 | public static void main(String[] args) { 20 | Person p1 = new Person("gavin", 28); 21 | Person p2 = new Person("zora", 27); 22 | 23 | Person[] lover = {p1, p2}; 24 | 25 | for (Person person : lover) { 26 | System.out.println(person.name + " : " + person.age); 27 | } 28 | 29 | System.out.println("----- 排序后 -----"); 30 | 31 | Arrays.sort(lover, new ComparatorImpl()); 32 | 33 | for (Person person : lover) { 34 | System.out.println(person.name + " : " + person.age); 35 | } 36 | } 37 | } 38 | 39 | class Person { 40 | String name; 41 | int age; 42 | 43 | public Person(String name, int age) { 44 | this.name = name; 45 | this.age = age; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter14/GenericAndUpcasting.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter14; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * author:Charies Gavin 8 | * date:2018/4/22,11:10 9 | * https:github.com/guobinhit 10 | * description:泛型和向上转型 11 | */ 12 | public class GenericAndUpcasting { 13 | public static void main(String[] args) { 14 | List animals = new ArrayList(); 15 | 16 | animals.add(new Cat()); 17 | animals.add(new Dog()); 18 | animals.add(new Tiger()); 19 | 20 | for (Animal animal : animals) { 21 | System.out.println(animal); 22 | } 23 | } 24 | } 25 | 26 | class Animal { 27 | } 28 | 29 | class Cat extends Animal { 30 | } 31 | 32 | class Dog extends Animal { 33 | } 34 | 35 | class Tiger extends Animal { 36 | } 37 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter14/MultidimensionalArray.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter14; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/4/22,11:30 8 | * https:github.com/guobinhit 9 | * description:多维数组 10 | */ 11 | public class MultidimensionalArray { 12 | public static void main(String[] args) { 13 | // 初始化多维数组 14 | int[][] multi = { 15 | {1, 1, 2, 0}, 16 | {2, 0, 1, 5} 17 | }; 18 | 19 | System.out.println("打印多维数组:" + Arrays.deepToString(multi)); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter14/ParameterizedArrayType.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter14; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/4/22,12:10 6 | * https:github.com/guobinhit 7 | * description:参数化数组类型 8 | */ 9 | public class ParameterizedArrayType { 10 | public static void main(String[] args) { 11 | Integer[] ints = {1, 1, 2, 0}; 12 | Double[] doubles = {1.1, 1.1, 2.2, 0.0}; 13 | Integer[] ints2 = new ClassParameter().f(ints); 14 | Double[] doubles2 = new ClassParameter().f(doubles); 15 | // ints2 = new MethodParameter.f(ints); 16 | // doubles2 = new MethodParameter.f(doubles); 17 | } 18 | } 19 | 20 | class ClassParameter { 21 | public T[] f(T[] arg) { 22 | return arg; 23 | } 24 | } 25 | 26 | class MethodParameter { 27 | public static T[] f(T[] arg) { 28 | return arg; 29 | } 30 | } 31 | 32 | 33 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter14/QueueDemo.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter14; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | import java.util.Random; 6 | 7 | /** 8 | * author:Charies Gavin 9 | * date:2018/4/23,9:30 10 | * https:github.com/guobinhit 11 | * description:测试队列 12 | */ 13 | public class QueueDemo { 14 | public static void main(String[] args) { 15 | Queue integerQueue = new LinkedList(); 16 | 17 | Random random = new Random(47); 18 | 19 | for (int i = 0; i < 5; i++) { 20 | // offer() 将元素插入对尾 21 | integerQueue.offer(random.nextInt(i + 10)); 22 | } 23 | 24 | printQueue(integerQueue); 25 | 26 | Queue stringQueue = new LinkedList(); 27 | 28 | for (String str : "May the force with you".split(" ")) { 29 | // offer() 将元素插入对尾 30 | stringQueue.offer(str); 31 | } 32 | 33 | printQueue(stringQueue); 34 | } 35 | 36 | private static void printQueue(Queue queue) { 37 | // peek() 在移除元素的情况下,返回对头元素,如果对头元素不为 null,则说明队列不为空 38 | while (queue.peek() != null) { 39 | // remove() 移除并返回对头元素 40 | System.out.println(queue.remove() + " "); 41 | } 42 | System.out.println(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter14/SimpleIteration.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter14; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Iterator; 5 | import java.util.List; 6 | 7 | /** 8 | * author:Charies Gavin 9 | * date:2018/4/22,14:00 10 | * https:github.com/guobinhit 11 | * description:测试迭代器效果 12 | */ 13 | public class SimpleIteration { 14 | public static void main(String[] args) { 15 | List list = new ArrayList(); 16 | 17 | list.add("Zora"); 18 | list.add("I"); 19 | list.add("love"); 20 | list.add("you"); 21 | 22 | // 获取容器的迭代器对象 23 | Iterator it = list.iterator(); 24 | 25 | // 判断序列是否还有元素 26 | while (it.hasNext()) { 27 | // 获取下一个元素,首次调用获取第一个元素 28 | String str = (String) it.next(); 29 | System.out.println(str); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter14/Stack.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter14; 2 | 3 | import java.util.LinkedList; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/4/23,9:00 8 | * https:github.com/guobinhit 9 | * description:用LinkedList实现栈 10 | */ 11 | public class Stack { 12 | private LinkedList storage = new LinkedList(); 13 | 14 | // 压栈方法,用于存入元素 15 | public void push(T element) { 16 | storage.addFirst(element); 17 | } 18 | 19 | // 获取栈中第一个存入的元素 20 | public T peek() { 21 | return storage.getFirst(); 22 | } 23 | 24 | // 弹栈方法,移除最后一个入栈元素 25 | public T pop() { 26 | return storage.removeFirst(); 27 | } 28 | 29 | // 判断栈是否为空 30 | public boolean isEmpty() { 31 | return storage.isEmpty(); 32 | } 33 | 34 | // 打印栈 35 | public String toString() { 36 | return storage.toString(); 37 | } 38 | 39 | public static void main(String[] args) { 40 | Stack stack = new Stack(); 41 | 42 | // 循环入栈 43 | for (String str : "Hi girl what is your name".split(" ")) { 44 | stack.push(str); 45 | } 46 | 47 | // 循环出栈 48 | while (!stack.isEmpty()) { 49 | System.out.println(stack.pop() + " "); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter14/TestContainer.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter14; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/4/23,8:30 8 | * https:github.com/guobinhit 9 | * description:测试容器 10 | */ 11 | public class TestContainer { 12 | public static void main(String[] args) { 13 | System.out.println(fill(new ArrayList())); 14 | System.out.println(fill(new LinkedList())); 15 | System.out.println(fill(new HashSet())); 16 | System.out.println(fill(new TreeSet())); 17 | System.out.println(fill(new LinkedHashSet())); 18 | System.out.println(fill(new HashMap())); 19 | System.out.println(fill(new TreeMap())); 20 | System.out.println(fill(new LinkedHashMap())); 21 | } 22 | 23 | /** 24 | * 填充Collection 25 | * 26 | * @param collection 27 | * @return Collection 28 | */ 29 | private static Collection fill(Collection collection) { 30 | collection.add("Baidu"); 31 | collection.add("Alibaba"); 32 | collection.add("Tencent"); 33 | collection.add("Twitter"); 34 | collection.add("Google"); 35 | collection.add("Facebook"); 36 | collection.add("Baidu"); 37 | return collection; 38 | } 39 | 40 | /** 41 | * 填充Map 42 | * 43 | * @param map 44 | * @return Map 45 | */ 46 | private static Map fill(Map map) { 47 | map.put("Robin Li", "Baidu"); 48 | map.put("Jack Ma", "Alibaba"); 49 | map.put("Pony", "Tencent"); 50 | map.put("Evan Williams", "Twitter"); 51 | map.put("Larry Page", "Google"); 52 | map.put("Mark Zuckerberg", "Facebook"); 53 | map.put("Robin Li", "Baidu"); 54 | return map; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter15/FullContainer.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter15; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/5/5,9:30 8 | * https:github.com/guobinhit 9 | * description:填充容器 10 | */ 11 | public class FullContainer { 12 | public static void main(String[] args) { 13 | // 使用 Collections 的 fill() 方法填充 List 对象 14 | List stringList = new ArrayList(Collections.nCopies(10, "Hello")); 15 | Collections.fill(stringList, "World"); 16 | System.out.println(stringList); 17 | 18 | // 将一个容器对象当做参数传给另一个容器对象的构造器 19 | List fullList = new ArrayList(stringList); 20 | System.out.println(fullList); 21 | 22 | // 打印 TreeSet 的比较器 23 | SortedSet sortedSet = new TreeSet(); 24 | System.out.println(sortedSet.comparator()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter15/Groundhog.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter15; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/5/5,10:00 6 | * https:github.com/guobinhit 7 | * description:土拨鼠 8 | */ 9 | public class Groundhog { 10 | protected int number; 11 | 12 | public Groundhog(int n) { 13 | number = n; 14 | } 15 | 16 | @Override 17 | public String toString() { 18 | return "Groundhog #" + number; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter15/Groundhot2.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter15; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/5/5,10:05 6 | * https:github.com/guobinhit 7 | * description:土拨鼠2 8 | */ 9 | public class Groundhot2 extends Groundhog { 10 | public Groundhot2(int n) { 11 | super(n); 12 | } 13 | 14 | /** 15 | * 覆盖 hashCode() 方法,由于示例比较简单,且 number 不会重复,因此直接返回 number 即可 16 | */ 17 | @Override 18 | public int hashCode() { 19 | return number; 20 | } 21 | 22 | /** 23 | * 覆盖 equals() 方法,Object 默认的 equals() 方法比较的是对象的地址 24 | * 操作符 instanceof 会悄悄地检查此对象是否为 null,如果其左边对象的参数为 null,则返回 false 25 | */ 26 | @Override 27 | public boolean equals(Object o) { 28 | return o instanceof Groundhot2 && (number == ((Groundhot2) o).number); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter15/Prediction.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter15; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/5/5,10:10 8 | * https:github.com/guobinhit 9 | * description:预测 10 | */ 11 | public class Prediction { 12 | private static Random random = new Random(47); 13 | private boolean shadow = random.nextDouble() > 0.5; 14 | 15 | @Override 16 | public String toString() { 17 | if (shadow) { 18 | return "Six more weeks of Winter!"; 19 | } else { 20 | return "Early String!"; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter15/ReadOnly.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter15; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/5/5,18:20 8 | * https:github.com/guobinhit 9 | * description:只读容器 10 | */ 11 | public class ReadOnly { 12 | public static void main(String[] args) { 13 | Collection collection = new ArrayList(); 14 | 15 | collection.add("Blank Panther"); 16 | collection.add("Doctor Strange"); 17 | collection.add("Iron Man"); 18 | 19 | List list = Collections.unmodifiableList(new ArrayList(collection)); 20 | Set set = Collections.unmodifiableSet(new HashSet(collection)); 21 | 22 | System.out.println(list); 23 | System.out.println(set); 24 | 25 | // 下面的添加语句会引起 UnsupportedOperationException 异常 26 | list.add("Captain America"); 27 | System.out.println(list); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter15/SpringDetector.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter15; 2 | 3 | import java.lang.reflect.Constructor; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | /** 8 | * author:Charies Gavin 9 | * date:2018/5/5,10:30 10 | * https:github.com/guobinhit 11 | * description:春天探测 12 | */ 13 | public class SpringDetector { 14 | /** 15 | * 由于通过反射获取类构造器的时候,有可能出现 NoSuchMethodException,因此直接在方法定义上进行声明 16 | * 17 | * @param type 18 | * @param 19 | * @throws Exception 20 | */ 21 | public static void detectSpring(Class type) throws Exception { 22 | // 通过反射获取类构造器,有可能出现 NoSuchMethodException 23 | Constructor ghot = type.getConstructor(int.class); 24 | 25 | Map map = new HashMap(); 26 | 27 | for (int i = 0; i < 10; i++) { 28 | map.put(ghot.newInstance(i), new Prediction()); 29 | } 30 | 31 | // 格式化打印的格式 32 | for (Groundhog groundhog : map.keySet()) { 33 | System.out.println(groundhog + " : " + map.get(groundhog)); 34 | } 35 | 36 | // 又创建了一个 Groundhog 对象 37 | Groundhog gh = ghot.newInstance(3); 38 | 39 | System.out.println("Looking up prediction for " + gh); 40 | 41 | if (map.containsKey(gh)) { 42 | System.out.println(map.get(gh)); 43 | } else { 44 | System.out.println("Key not found: " + gh); 45 | } 46 | } 47 | 48 | public static void main(String[] args) throws Exception { 49 | // 由于 Groundhog 未覆盖 equals() 方法,因此默认比较对象的地址 50 | detectSpring(Groundhog.class); 51 | 52 | System.out.println("------ ****** ------"); 53 | 54 | // 在 Groundhot2 中覆盖了 equals() 方法,比较对象 number 的值 55 | detectSpring(Groundhot2.class); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter15/mapself/MapEntry.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter15.mapself; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/5/5,12:30 8 | * https:github.com/guobinhit 9 | * description:Override some Object method 10 | */ 11 | public class MapEntry implements Map.Entry { 12 | private K key; 13 | private V value; 14 | 15 | public MapEntry(K key, V value) { 16 | this.key = key; 17 | this.value = value; 18 | } 19 | 20 | @Override 21 | public K getKey() { 22 | return key; 23 | } 24 | 25 | @Override 26 | public V getValue() { 27 | return value; 28 | } 29 | 30 | @Override 31 | public V setValue(V v) { 32 | V result = value; 33 | value = v; 34 | return result; 35 | } 36 | 37 | @Override 38 | public int hashCode() { 39 | return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode()); 40 | } 41 | 42 | @Override 43 | public boolean equals(Object o) { 44 | if (!(o instanceof MapEntry)) { 45 | return false; 46 | } 47 | MapEntry me = (MapEntry) o; 48 | return (key == null ? me.getKey() == null : key.equals(me.getKey())) && 49 | (value == null ? me.getValue() == null : value.equals(me.getValue())); 50 | } 51 | 52 | @Override 53 | public String toString() { 54 | return key + " = " + value; 55 | } 56 | } -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter15/mapself/SlowMap.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter15.mapself; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/5/5,13:00 8 | * https:github.com/guobinhit 9 | * description:SlowMap 10 | */ 11 | public class SlowMap extends AbstractMap { 12 | private List keys = new ArrayList(); 13 | private List values = new ArrayList(); 14 | 15 | public V put(K key, V value) { 16 | // the old value or null 17 | V oldValue = get(key); 18 | if (!keys.contains(key)) { 19 | keys.add(key); 20 | values.add(value); 21 | } else { 22 | values.set(keys.indexOf(key), value); 23 | } 24 | return oldValue; 25 | } 26 | 27 | /** 28 | * key is type Object, not K 29 | * 30 | * @param key 31 | * @return value 32 | */ 33 | public V get(Object key) { 34 | if (!keys.contains(key)) { 35 | return null; 36 | } else { 37 | return values.get(keys.indexOf(key)); 38 | } 39 | } 40 | 41 | @Override 42 | public Set> entrySet() { 43 | Set> set = new HashSet>(); 44 | Iterator ki = keys.iterator(); 45 | Iterator vi = values.iterator(); 46 | while (ki.hasNext()) { 47 | set.add(new MapEntry(ki.next(), vi.next())); 48 | } 49 | return set; 50 | } 51 | 52 | public static void main(String[] args) { 53 | SlowMap slowMap = new SlowMap(); 54 | slowMap.put("Beijing", "Beijing"); 55 | slowMap.put("Heilongjiang", "Harbin"); 56 | slowMap.put("Hebei", "Shijiazhuang"); 57 | System.out.println(slowMap); 58 | System.out.println(slowMap.get("Beijing")); 59 | System.out.println(slowMap.get("")); 60 | System.out.println(slowMap.entrySet()); 61 | System.out.println(slowMap.put("Hebei", "Hengshui")); 62 | System.out.println(slowMap); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/BinaryFile.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter16; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.File; 5 | import java.io.FileInputStream; 6 | import java.io.IOException; 7 | 8 | /** 9 | * author:Charies Gavin 10 | * date:2018/6/26,9:00 11 | * https:github.com/guobinhit 12 | * description:读取二进制文件 13 | */ 14 | public class BinaryFile { 15 | public static byte[] read(File bFile) throws IOException { 16 | BufferedInputStream br = new BufferedInputStream( 17 | new FileInputStream(bFile) 18 | ); 19 | 20 | try { 21 | byte[] data = new byte[br.available()]; 22 | br.read(data); 23 | return data; 24 | } finally { 25 | br.close(); 26 | } 27 | } 28 | 29 | public static byte[] read(String bFile) throws IOException { 30 | return read(new File(bFile).getAbsoluteFile()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/ChangeSystemOut.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter16; 2 | 3 | import java.io.PrintWriter; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/6/26,9:14 8 | * https:github.com/guobinhit 9 | * description:改变输出流 10 | */ 11 | public class ChangeSystemOut { 12 | public static void main(String[] args) { 13 | /** 14 | * 需要使用 PrintWriter 两个参数的构造器,并将第二个参数设置为 true 15 | * 以便开启自动清空功能,否则,我们将看不到输出的内容 16 | */ 17 | PrintWriter out = new PrintWriter(System.out, true); 18 | out.println("Hello World"); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/Constants.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter16; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/5/6,13:00 6 | * https:github.com/guobinhit 7 | * description:常量类 8 | */ 9 | public class Constants { 10 | // 私有化构造函数 11 | private Constants() { 12 | } 13 | 14 | // 文件的绝对路径 15 | public static final String FILE_ABSOLUTE_PATH = "/Users/bin.guo/Documents/GitRepo/java-skills/PROJECT_CODE/javaskills/src/com/hit/thought/chapter16/io/"; 16 | 17 | // 文件的绝对路径,排除 io 目录 18 | public static final String FILE_ABSOLUTE_PATH_EXCLUDE_IO = "/Users/bin.guo/Documents/GitRepo/java-skills/PROJECT_CODE/javaskills/src/com/hit/thought/chapter16/"; 19 | 20 | // 文件的绝对路径 21 | public static final String FILE_ABSOLUTE_PATH_NIO = "/Users/bin.guo/Documents/GitRepo/java-skills/PROJECT_CODE/javaskills/src/com/hit/thought/chapter16/nio/"; 22 | } -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/DirList.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter16; 2 | 3 | import java.io.File; 4 | import java.io.FilenameFilter; 5 | import java.util.Arrays; 6 | import java.util.regex.Pattern; 7 | 8 | /** 9 | * author:Charies Gavin 10 | * date:2018/5/6,9:45 11 | * https:github.com/guobinhit 12 | * description:测试 File 类 13 | */ 14 | public class DirList { 15 | public static void main(String[] args) { 16 | /** 17 | * FIle(String pathName) or File(String pathName, String childName) 18 | * 19 | * File 有两个构造器,参数代表着文件路径的名称,如果有两个参数,则 20 | * 1、第一个参数,代表父路径; 21 | * 2、第二个参数,代表子路径。 22 | * 23 | * 如果 File 构造器参数为 . 则代表当前路径 24 | */ 25 | File path = new File("."); 26 | String[] list; 27 | if (args.length == 0) { 28 | list = path.list(); 29 | } else { 30 | list = path.list(new DirFilter(args[0])); 31 | } 32 | Arrays.sort(list, String.CASE_INSENSITIVE_ORDER); 33 | for (String dirItem : list) { 34 | System.out.println(dirItem); 35 | } 36 | } 37 | } 38 | 39 | /** 40 | * DirFilter 类存在的唯一目的就是实现我们自己的 accept() 方法,以实现回调 41 | */ 42 | class DirFilter implements FilenameFilter { 43 | private Pattern pattern; 44 | 45 | public DirFilter(String regex) { 46 | pattern = Pattern.compile(regex); 47 | } 48 | 49 | /** 50 | * accept() 方法必须接受一个代表某个特定文件所在目录的 File 对象,以及包含了那个文件名的一个 String 51 | * list() 方法会为此目录对象下的每个文件名调用 accept() 方法, 52 | * 来判断是否包含在内,判断的结果又 accept() 方法返回的 boolean 值表示。 53 | *

54 | * accept() 会使用正则表达式的 matcher 对象,来查看此正则表达式 regex 是否匹配这个文件的名字, 55 | * 通过使用 accept() 方法,list() 方法会返回一个数组 56 | */ 57 | @Override 58 | public boolean accept(File file, String name) { 59 | return pattern.matcher(name).matches(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/DirList2.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter16; 2 | 3 | import java.io.File; 4 | import java.io.FilenameFilter; 5 | import java.util.Arrays; 6 | import java.util.regex.Pattern; 7 | 8 | /** 9 | * author:Charies Gavin 10 | * date:2018/5/6,9:50 11 | * https:github.com/guobinhit 12 | * description:使用匿名内部类测试 File 类 13 | */ 14 | public class DirList2 { 15 | // 如果匿名内部类中用到了外部参数,需要将参数声明为 final 类型 16 | private static FilenameFilter filter(final String regex) { 17 | // 创建一个匿名内部类 18 | return new FilenameFilter() { 19 | private Pattern pattern = Pattern.compile(regex); 20 | 21 | @Override 22 | public boolean accept(File file, String name) { 23 | return pattern.matcher(name).matches(); 24 | } 25 | }; 26 | } 27 | 28 | public static void main(String[] args) { 29 | File path = new File("."); 30 | String[] list; 31 | if (args.length == 0) { 32 | list = path.list(); 33 | } else { 34 | list = path.list(filter(args[0])); 35 | } 36 | Arrays.sort(list, String.CASE_INSENSITIVE_ORDER); 37 | for (String dirItem : list) { 38 | System.out.println(dirItem); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/DirList3.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter16; 2 | 3 | import java.io.File; 4 | import java.io.FilenameFilter; 5 | import java.util.Arrays; 6 | import java.util.regex.Pattern; 7 | 8 | /** 9 | * author:Charies Gavin 10 | * date:2018/5/6,10:00 11 | * https:github.com/guobinhit 12 | * description:第三种测试 File 类的方法 13 | */ 14 | public class DirList3 { 15 | public static void main(final String[] args) { 16 | final File path = new File("."); 17 | String[] lsit; 18 | if (args.length == 0) { 19 | lsit = path.list(); 20 | } else { 21 | lsit = path.list(new FilenameFilter() { 22 | private Pattern pattern = Pattern.compile(args[0]); 23 | 24 | @Override 25 | public boolean accept(File file, String name) { 26 | return pattern.matcher(name).matches(); 27 | } 28 | }); 29 | } 30 | Arrays.sort(lsit, String.CASE_INSENSITIVE_ORDER); 31 | for (String dirItem : lsit) { 32 | System.out.println(dirItem); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/Echo.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter16; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | 7 | /** 8 | * author:Charies Gavin 9 | * date:2018/6/26,9:07 10 | * https:github.com/guobinhit 11 | * description:回显控制台输入的内容 12 | */ 13 | public class Echo { 14 | public static void main(String[] args) throws IOException { 15 | System.out.println("请输入需要回显的内容:"); 16 | 17 | // 由于 System.in 是未经包装的标准输入流,因此将其转为 BufferReader 18 | BufferedReader stdin = new BufferedReader( 19 | new InputStreamReader(System.in) 20 | ); 21 | 22 | String s; 23 | 24 | // 当程序收到 Ctrl + Z 的时候,终止程序 25 | while ((s = stdin.readLine()) != null && s.length() != 0) { 26 | System.out.println(s); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/Redirecting.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter16; 2 | 3 | import java.io.*; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/6/26,9:21 8 | * https:github.com/guobinhit 9 | * description:重定向标准 IO 流 10 | */ 11 | public class Redirecting { 12 | public static void main(String[] args) throws IOException { 13 | PrintStream console = System.out; 14 | BufferedInputStream in = new BufferedInputStream( 15 | new FileInputStream(Constants.FILE_ABSOLUTE_PATH_EXCLUDE_IO + "Redirecting.java") 16 | ); 17 | PrintStream out = new PrintStream( 18 | new BufferedOutputStream( 19 | new FileOutputStream(Constants.FILE_ABSOLUTE_PATH_EXCLUDE_IO + "redirecting.out") 20 | ) 21 | ); 22 | System.setIn(in); 23 | System.setOut(out); 24 | System.setErr(out); 25 | BufferedReader br = new BufferedReader( 26 | new InputStreamReader(System.in) 27 | ); 28 | String s; 29 | while ((s = br.readLine()) != null) { 30 | System.out.println(s); 31 | } 32 | out.close(); 33 | System.setOut(console); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/io/BasicFileOutput.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter16.io; 2 | 3 | import com.hit.thought.chapter16.Constants; 4 | 5 | import java.io.*; 6 | 7 | /** 8 | * author:Charies Gavin 9 | * date:2018/5/6,14:30 10 | * https:github.com/guobinhit 11 | * description:缓存输入与输出 12 | */ 13 | public class BasicFileOutput { 14 | private static String file = Constants.FILE_ABSOLUTE_PATH + "BasicFileOutput.out"; 15 | 16 | public static void main(String[] args) throws IOException { 17 | BufferedReader in = new BufferedReader( 18 | new StringReader( 19 | BufferedInputFile.read(Constants.FILE_ABSOLUTE_PATH + "BasicFileOutput.java") 20 | ) 21 | ); 22 | 23 | /** 24 | * FileWriter 对象可以向文件写入数据 25 | */ 26 | PrintWriter out = new PrintWriter( 27 | new BufferedWriter( 28 | new FileWriter(file) 29 | ) 30 | ); 31 | 32 | // 用于显示行号 33 | int lineCount = 1; 34 | String s; 35 | while ((s = in.readLine()) != null) { 36 | out.println(lineCount++ + " : " + s); 37 | } 38 | out.close(); 39 | System.out.println(BufferedInputFile.read(file)); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/io/BasicFileOutput.out: -------------------------------------------------------------------------------- 1 | 1 : package com.hit.thought.chapter16.io; 2 | 2 : 3 | 3 : import com.hit.thought.chapter16.Constants; 4 | 4 : 5 | 5 : import java.io.*; 6 | 6 : 7 | 7 : /** 8 | 8 : * author:Charies Gavin 9 | 9 : * date:2018/5/6,14:30 10 | 10 : * https:github.com/guobinhit 11 | 11 : * description:缓存输入与输出 12 | 12 : */ 13 | 13 : public class BasicFileOutput { 14 | 14 : private static String file = Constants.FILE_ABSOLUTE_PATH + "BasicFileOutput.out"; 15 | 15 : 16 | 16 : public static void main(String[] args) throws IOException { 17 | 17 : BufferedReader in = new BufferedReader( 18 | 18 : new StringReader( 19 | 19 : BufferedInputFile.read(Constants.FILE_ABSOLUTE_PATH + "BasicFileOutput.java") 20 | 20 : ) 21 | 21 : ); 22 | 22 : 23 | 23 : /** 24 | 24 : * FileWriter 对象可以向文件写入数据 25 | 25 : */ 26 | 26 : PrintWriter out = new PrintWriter( 27 | 27 : new BufferedWriter( 28 | 28 : new FileWriter(file) 29 | 29 : ) 30 | 30 : ); 31 | 31 : 32 | 32 : // 用于显示行号 33 | 33 : int lineCount = 1; 34 | 34 : String s; 35 | 35 : while ((s = in.readLine()) != null) { 36 | 36 : out.println(lineCount++ + " : " + s); 37 | 37 : } 38 | 38 : out.close(); 39 | 39 : System.out.println(BufferedInputFile.read(file)); 40 | 40 : } 41 | 41 : } 42 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/io/BufferedInputFile.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter16.io; 2 | 3 | import com.hit.thought.chapter16.Constants; 4 | 5 | import java.io.BufferedReader; 6 | import java.io.FileReader; 7 | import java.io.IOException; 8 | 9 | /** 10 | * author:Charies Gavin 11 | * date:2018/5/6,13:20 12 | * https:github.com/guobinhit 13 | * description:缓冲输入流 14 | */ 15 | public class BufferedInputFile { 16 | /** 17 | * 将异常抛到控制台 18 | * 19 | * @param filename 此参数为文件的全路径,例如:/Users/bin.guo/Documents/GitRepo/java-skills/PROJECT_CODE/javaskills/src/com/hit/thought/chapter16/io/BufferedInputFile.java 20 | * @return 文件内容 21 | * @throws IOException 22 | */ 23 | public static String read(String filename) throws IOException { 24 | // 按行读取输入 25 | BufferedReader in = new BufferedReader(new FileReader(filename)); 26 | String s; 27 | StringBuilder sb = new StringBuilder(); 28 | while ((s = in.readLine()) != null) { 29 | sb.append(s + "\n"); 30 | } 31 | // 特别注意:一定要记得关闭流 32 | in.close(); 33 | return sb.toString(); 34 | } 35 | 36 | public static void main(String[] args) throws IOException { 37 | System.out.println(read(Constants.FILE_ABSOLUTE_PATH + "BufferedInputFile.java")); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/io/Data.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/javaskills/src/com/hit/thought/chapter16/io/Data.txt -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/io/FileOutputShortcut.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter16.io; 2 | 3 | import com.hit.thought.chapter16.Constants; 4 | 5 | import java.io.*; 6 | 7 | /** 8 | * author:Charies Gavin 9 | * date:2018/5/6,15:00 10 | * https:github.com/guobinhit 11 | * description:优化缓存输入和输出 12 | */ 13 | public class FileOutputShortcut { 14 | private static String file = Constants.FILE_ABSOLUTE_PATH + "FileOutputShortcut.out"; 15 | 16 | public static void main(String[] args) throws IOException { 17 | BufferedReader in = new BufferedReader( 18 | new StringReader( 19 | BufferedInputFile.read(Constants.FILE_ABSOLUTE_PATH + "FileOutputShortcut.java") 20 | ) 21 | ); 22 | 23 | /** 24 | * 在 Java SE5 中,PrintWriter 新增了一个辅助构造器, 25 | * 使得我们不必在每次希望创建文本文件并向其中写入时, 26 | * 都去执行所有的装饰工作 27 | */ 28 | PrintWriter out = new PrintWriter(file); 29 | 30 | // 用于显示行号 31 | int lineCount = 1; 32 | String s; 33 | while ((s = in.readLine()) != null) { 34 | out.println(lineCount++ + " : " + s); 35 | } 36 | out.close(); 37 | System.out.println(BufferedInputFile.read(file)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/io/FileOutputShortcut.out: -------------------------------------------------------------------------------- 1 | 1 : package com.hit.thought.chapter16.io; 2 | 2 : 3 | 3 : import com.hit.thought.chapter16.Constants; 4 | 4 : 5 | 5 : import java.io.*; 6 | 6 : 7 | 7 : /** 8 | 8 : * author:Charies Gavin 9 | 9 : * date:2018/5/6,15:00 10 | 10 : * https:github.com/guobinhit 11 | 11 : * description:优化缓存输入和输出 12 | 12 : */ 13 | 13 : public class FileOutputShortcut { 14 | 14 : private static String file = Constants.FILE_ABSOLUTE_PATH + "FileOutputShortcut.out"; 15 | 15 : 16 | 16 : public static void main(String[] args) throws IOException { 17 | 17 : BufferedReader in = new BufferedReader( 18 | 18 : new StringReader( 19 | 19 : BufferedInputFile.read(Constants.FILE_ABSOLUTE_PATH + "FileOutputShortcut.java") 20 | 20 : ) 21 | 21 : ); 22 | 22 : 23 | 23 : /** 24 | 24 : * 在 Java SE5 中,PrintWriter 新增了一个辅助构造器, 25 | 25 : * 使得我们不必在每次希望创建文本文件并向其中写入时, 26 | 26 : * 都去执行所有的装饰工作 27 | 27 : */ 28 | 28 : PrintWriter out = new PrintWriter(file); 29 | 29 : 30 | 30 : // 用于显示行号 31 | 31 : int lineCount = 1; 32 | 32 : String s; 33 | 33 : while ((s = in.readLine()) != null) { 34 | 34 : out.println(lineCount++ + " : " + s); 35 | 35 : } 36 | 36 : out.close(); 37 | 37 : System.out.println(BufferedInputFile.read(file)); 38 | 38 : } 39 | 39 : } 40 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/io/FormattedMemoryInput.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter16.io; 2 | 3 | import com.hit.thought.chapter16.Constants; 4 | 5 | import java.io.ByteArrayInputStream; 6 | import java.io.DataInputStream; 7 | import java.io.EOFException; 8 | import java.io.IOException; 9 | 10 | /** 11 | * author:Charies Gavin 12 | * date:2018/5/6,13:45 13 | * https:github.com/guobinhit 14 | * description:格式化内存输入 15 | */ 16 | public class FormattedMemoryInput { 17 | public static void main(String[] args) throws IOException { 18 | try { 19 | /** 20 | * 要读取格式化数据,可以使用 DataInputStream,它是一个面向字节的 I/O 类; 21 | * 此外,必须向 ByteArrayInputStream 提供字节数组 22 | */ 23 | DataInputStream in = new DataInputStream( 24 | new ByteArrayInputStream( 25 | BufferedInputFile.read(Constants.FILE_ABSOLUTE_PATH + "FormattedMemoryInput.java") 26 | .getBytes() 27 | )); 28 | while (true) { 29 | System.out.println((char) in.readByte()); 30 | } 31 | } catch (EOFException e) { // EOF 表示 end of file,此异常表示文件已读取完毕 32 | System.out.println("End of Stream"); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/io/MemoryInput.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter16.io; 2 | 3 | import com.hit.thought.chapter16.Constants; 4 | 5 | import java.io.IOException; 6 | import java.io.StringReader; 7 | 8 | /** 9 | * author:Charies Gavin 10 | * date:2018/5/6,13:30 11 | * https:github.com/guobinhit 12 | * description:内存输入 13 | */ 14 | public class MemoryInput { 15 | public static void main(String[] args) throws IOException { 16 | StringReader in = new StringReader(BufferedInputFile.read(Constants.FILE_ABSOLUTE_PATH + "MemoryInput.java")); 17 | int c; 18 | // 此对象用于积累文件的内容,与 while 循环输出的内容做对比 19 | StringBuilder sb = new StringBuilder(); 20 | while ((c = in.read()) != -1) { 21 | sb.append((char) c); 22 | 23 | /** 24 | * read() 方法是以 int 形式返回下一个字节, 25 | * 因此必须将类型转换为 char 才能正确打印 26 | */ 27 | System.out.println((char) c); 28 | } 29 | System.out.println(sb); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/io/StoringAndRecoveringData.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter16.io; 2 | 3 | import com.hit.thought.chapter16.Constants; 4 | 5 | import java.io.*; 6 | 7 | /** 8 | * author:Charies Gavin 9 | * date:2018/6/25,8:38 10 | * https:github.com/guobinhit 11 | * description:存储和恢复数据 12 | */ 13 | public class StoringAndRecoveringData { 14 | public static void main(String[] args) throws IOException { 15 | DataOutputStream out = new DataOutputStream( 16 | new BufferedOutputStream( 17 | new FileOutputStream(Constants.FILE_ABSOLUTE_PATH + "Data.txt") 18 | ) 19 | ); 20 | 21 | out.writeDouble(3.14159); 22 | out.writeUTF("That was pi"); 23 | out.writeDouble(1.41413); 24 | out.writeUTF("Square root of 2"); 25 | out.close(); 26 | 27 | DataInputStream in = new DataInputStream( 28 | new BufferedInputStream( 29 | new FileInputStream(Constants.FILE_ABSOLUTE_PATH + "Data.txt") 30 | ) 31 | ); 32 | 33 | System.out.println(in.readDouble()); 34 | // Only readUTF() will recover the Java-UTF String proper;y 35 | System.out.println(in.readUTF()); 36 | System.out.println(in.readDouble()); 37 | System.out.println(in.readUTF()); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/io/TestEOF.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter16.io; 2 | 3 | import com.hit.thought.chapter16.Constants; 4 | 5 | import java.io.BufferedInputStream; 6 | import java.io.DataInputStream; 7 | import java.io.FileInputStream; 8 | import java.io.IOException; 9 | 10 | /** 11 | * author:Charies Gavin 12 | * date:2018/5/6,14:00 13 | * https:github.com/guobinhit 14 | * description:测试 EOF 异常 15 | */ 16 | public class TestEOF { 17 | public static void main(String[] args) throws IOException { 18 | DataInputStream in = new DataInputStream( 19 | new BufferedInputStream( 20 | new FileInputStream(Constants.FILE_ABSOLUTE_PATH + "TestEOF.java") 21 | ) 22 | ); 23 | 24 | /** 25 | * 如果我们从 DataInputStream 用 readByte() 一次一个字节地读取字符, 26 | * 那么任何字节的值都是合法的结果,因此返回值不能用来检查输入是否结束。 27 | * 28 | * 相反,我们可以使用 available() 方法来查看还有多少可供存取的字符, 29 | * 因此,可以避免对 EOFException 的捕获和判断。 30 | * 31 | * 但是,available() 的工作方式会随着所读取的媒介类型的不同而有所不同; 32 | * 字面意思就是"在没有阻塞的情况下所能读取的字节数"。 33 | * 对于文件,意味着整个文件;对于不同类型的流,可能就不是这样的,因此要谨慎使用。 34 | * 35 | * 虽然我们可以通过捕获异常来检测输入的末尾,但是,使用异常进行流控制,被认为是对异常特性的错误使用 36 | */ 37 | while (in.available() != 0) { 38 | System.out.println((char) in.readByte()); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/io/UsingRandomAccessFIle.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter16.io; 2 | 3 | import com.hit.thought.chapter16.Constants; 4 | 5 | import java.io.IOException; 6 | import java.io.RandomAccessFile; 7 | 8 | /** 9 | * author:Charies Gavin 10 | * date:2018/6/25,8:49 11 | * https:github.com/guobinhit 12 | * description:读取随机访问文件 13 | */ 14 | public class UsingRandomAccessFIle { 15 | static String file = Constants.FILE_ABSOLUTE_PATH + "rtest.dat"; 16 | 17 | /** 18 | * 读取文件并打印 19 | * 20 | * @throws IOException 21 | */ 22 | static void display() throws IOException { 23 | /** 24 | * RandomAccessFile 有两个构造器参数,分别为: 25 | * 1、fileName:表示文件名 26 | * 2、openMethod:表示打开文件的方式 27 | * 对于第二个参数,有两个指定的值,分别为: 28 | * r:表示以"只读"方式打开文件 29 | * rw:表示以"读写"方法打开文件 30 | */ 31 | RandomAccessFile rf = new RandomAccessFile(file, "r"); 32 | for (int i = 0; i < 7; i++) { 33 | System.out.println("Value " + i + ": " + rf.readDouble()); 34 | } 35 | System.out.println(rf.readUTF()); 36 | rf.close(); 37 | } 38 | 39 | public static void main(String[] args) throws IOException { 40 | // 写入文件 41 | RandomAccessFile rf = new RandomAccessFile(file, "rw"); 42 | for (int i = 0; i < 7; i++) { 43 | rf.writeDouble(i * 1.414); 44 | } 45 | rf.writeUTF("The end of the file"); 46 | rf.close(); 47 | 48 | display(); 49 | 50 | // 修改文件 51 | rf = new RandomAccessFile(file, "rw"); 52 | // 因为 double 总是 8 字节长,为了寻找第 5 个双精度值,我们需要用 5*8 来查找位置 53 | rf.seek(6 * 8); 54 | rf.writeDouble(47.0001); 55 | rf.close(); 56 | 57 | display(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/io/rtest.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guobinhit/java-skills/38860c71334063829c5994655305b1532a24d295/javaskills/src/com/hit/thought/chapter16/io/rtest.dat -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/nio/GetChannel.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter16.nio; 2 | 3 | import com.hit.thought.chapter12.reflect.B; 4 | import com.hit.thought.chapter16.Constants; 5 | 6 | import java.io.FileInputStream; 7 | import java.io.FileOutputStream; 8 | import java.io.IOException; 9 | import java.io.RandomAccessFile; 10 | import java.nio.ByteBuffer; 11 | import java.nio.channels.FileChannel; 12 | 13 | /** 14 | * @author bin.guo 15 | * @Copyright 易宝支付(YeePay) 16 | * @date 6/28/18,9:21 AM 17 | * @description 18 | */ 19 | public class GetChannel { 20 | private static final int BUFFER_SIZE = 1024; 21 | 22 | public static void main(String[] args) throws IOException { 23 | // Write a file 24 | FileChannel fc = new FileOutputStream( 25 | Constants.FILE_ABSOLUTE_PATH_NIO + "data.txt").getChannel(); 26 | fc.write(ByteBuffer.wrap("Hello World ".getBytes())); 27 | fc.close(); 28 | 29 | // Add to the end of the file 30 | fc = new RandomAccessFile( 31 | Constants.FILE_ABSOLUTE_PATH_NIO + "data.txt", "rw").getChannel(); 32 | fc.position(fc.size()); 33 | fc.write(ByteBuffer.wrap("See U!".getBytes())); 34 | fc.close(); 35 | 36 | // Read the file 37 | fc = new FileInputStream( 38 | Constants.FILE_ABSOLUTE_PATH_NIO + "data.txt").getChannel(); 39 | ByteBuffer buff = ByteBuffer.allocate(BUFFER_SIZE); 40 | fc.read(buff); 41 | buff.flip(); 42 | while (buff.hasRemaining()) { 43 | System.out.print((char) buff.get()); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/nio/data.txt: -------------------------------------------------------------------------------- 1 | Hello World See U! -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter16/redirecting.out: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter16; 2 | 3 | import java.io.*; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2018/6/26,9:21 8 | * https:github.com/guobinhit 9 | * description:重定向标准 IO 流 10 | */ 11 | public class Redirecting { 12 | public static void main(String[] args) throws IOException { 13 | PrintStream console = System.out; 14 | BufferedInputStream in = new BufferedInputStream( 15 | new FileInputStream(Constants.FILE_ABSOLUTE_PATH_EXCLUDE_IO + "Redirecting.java") 16 | ); 17 | PrintStream out = new PrintStream( 18 | new BufferedOutputStream( 19 | new FileOutputStream(Constants.FILE_ABSOLUTE_PATH_EXCLUDE_IO + "redirecting.out") 20 | ) 21 | ); 22 | System.setIn(in); 23 | System.setOut(out); 24 | System.setErr(out); 25 | BufferedReader br = new BufferedReader( 26 | new InputStreamReader(System.in) 27 | ); 28 | String s; 29 | while ((s = br.readLine()) != null) { 30 | System.out.println(s); 31 | } 32 | out.close(); 33 | System.setOut(console); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter2/DefaultValue.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter2; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2017/12/05,8:50 6 | * https:github.com/guobinhit 7 | * description:测试默认值 8 | */ 9 | public class DefaultValue { 10 | /** 11 | * 定义基本数据类型成员变量 12 | */ 13 | public static boolean aBoolean; 14 | public static char aChar; 15 | public static byte aByte; 16 | public static short aShort; 17 | public static int anInt; 18 | public static long aLong; 19 | public static float aFloat; 20 | public static double aDouble; 21 | 22 | public static int defaultValue(){ 23 | int x = 5211314; 24 | // int x; 25 | return x; 26 | } 27 | 28 | public static void main(String[] args) { 29 | /** 30 | * 直接输出未手动初始化的成员变量进行测试 31 | */ 32 | System.out.println("aBoolean : " + aBoolean + " aChar : " + aChar + " aByte : " + aByte + " aShort : " + aShort 33 | + " anInt : " + anInt + " aLong : " + aLong + " aFloat : " + aFloat + " aDouble : " + aDouble); 34 | 35 | /** 36 | * 直接输出在方法中未初始化的局部变量,编译器会报错 37 | */ 38 | System.out.println(defaultValue()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter3/ArithmeticOperator.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter3; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2017/12/09,13:50 8 | * https:github.com/guobinhit 9 | * description:测试算术操作符 10 | */ 11 | public class ArithmeticOperator { 12 | public static void main(String[] args) { 13 | /** 14 | * 测试随机整数除法 15 | */ 16 | randomDivide(); 17 | } 18 | 19 | /** 20 | * 随机整数除法 21 | */ 22 | private static void randomDivide() { 23 | Random random = new Random(); 24 | int x = random.nextInt(10) + 1; 25 | int y = random.nextInt(10) + 1; 26 | int z = x / y; 27 | System.out.println("整数除法,默认省略结果的小数位:" + x + " / " + y + " = " + z); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter3/AssignmentOperator.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter3; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2017/12/09,12:40 6 | * https:github.com/guobinhit 7 | * description:测试赋值操作符,赋值对象引用 8 | */ 9 | public class AssignmentOperator { 10 | public static void main(String[] args) { 11 | // 创建两个对象 12 | Apple apple1 = new Apple("green"); 13 | Apple apple2 = new Apple(); 14 | // 输出两个初始化对象,apple1 初始化 color 为 green,apple2 初始化 color 为 null 15 | System.out.println("Initial: apple1 color is " + apple1.color + ", apple2 color is " + apple2.color); 16 | // 将 apple1 的引用赋值给 apple2 17 | apple2 = apple1; 18 | // 输出赋值后的两个对象,两个对象拥有同一个引用 19 | System.out.println("Assignment: apple1 color is " + apple1.color + ", apple2 color is " + apple2.color); 20 | // 修改 apple2 的引用 21 | apple2.color = "red"; 22 | // 输出 apple2 修改后的两个对象,两个对象都发生变化 23 | System.out.println("Modify: apple1 color is " + apple1.color + ", apple2 color is " + apple2.color); 24 | } 25 | 26 | } 27 | 28 | class Apple { 29 | // 成员变量 30 | String color; 31 | 32 | /** 33 | * 默认构造器 34 | */ 35 | Apple() { 36 | } 37 | 38 | /** 39 | * 有参构造器 40 | * 41 | * @param color 42 | */ 43 | Apple(String color) { 44 | this.color = color; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter3/AssignmentOperator2.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter3; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2017/12/09,12:59 6 | * https:github.com/guobinhit 7 | * description:测试赋值操作符,赋值基本数据类型(同时也解决了同名现象) 8 | */ 9 | public class AssignmentOperator2 { 10 | public static void main(String[] args) { 11 | // 创建两个对象 12 | Book book1 = new Book(18); 13 | Book book2 = new Book(); 14 | // 输出两个初始化对象,book1 初始化 price 为 18,book2 初始化 price 为 0 15 | System.out.println("Initial: book1 price is " + book1.price + ", book2 price is " + book2.price); 16 | // 将 book1 的 price 值赋值给 book2 的 price 值 17 | book2.price = book1.price; 18 | // 输出赋值后的两个对象 19 | System.out.println("Assignment: book1 price is " + book1.price + ", book2 price is " + book2.price); 20 | // 修改 book2 的 price 值 21 | book2.price = 20; 22 | // 输出 book2 修改后的两个对象,由于两个对象拥有不同的引用,因此修改一个并不会影响另一个 23 | System.out.println("Modify: book1 price is " + book1.price + ", book2 price is " + book2.price); 24 | } 25 | } 26 | 27 | class Book { 28 | // 成员变量 29 | int price; 30 | 31 | /** 32 | * 默认构造器 33 | */ 34 | Book() { 35 | } 36 | 37 | /** 38 | * 有参构造器 39 | * 40 | * @param price 41 | */ 42 | Book(int price) { 43 | this.price = price; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter3/BasicTypeCast.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter3; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2017/12/09,16:50 6 | * https:github.com/guobinhit 7 | * description:数字类型转换 8 | */ 9 | public class BasicTypeCast { 10 | public static void main(String[] args) { 11 | // 定义变量并初始化 12 | float a = 0.3F, b = 0.6F; 13 | double c = 0.8D, d = 0.1D; 14 | // 调用 Math.round() 方法获取四舍五入的结果 15 | System.out.println("Math.rund(a): " + Math.round(a)); 16 | System.out.println("Math.rund(b): " + Math.round(b)); 17 | System.out.println("Math.rund(c): " + Math.round(c)); 18 | System.out.println("Math.rund(d): " + Math.round(d)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter3/Exponent.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter3; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2017/12/09,16:30 6 | * https:github.com/guobinhit 7 | * description:指数计数法 8 | */ 9 | public class Exponent { 10 | public static void main(String[] args) { 11 | // float loveu = 5e2f; 12 | /** 13 | * 在使用 指数计数法 的时候,编辑器默认将指数作为双精度数(double)来处理, 14 | * 如果初始化值后面没有 f 或者 F 的话,编译器会报错 15 | * 提示我们必须使用类型转换将 double 转换为 float 类型 16 | */ 17 | float loveu = 5.21e2F; 18 | System.out.println(loveu); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter3/RelationOperator.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter3; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2017/12/10,14:43 6 | * https:github.com/guobinhit 7 | * description:测试关系操作符 8 | */ 9 | public class RelationOperator { 10 | public static void main(String[] args) { 11 | // 创建两个 Integer 对象 12 | Integer i1 = new Integer(521); 13 | Integer i2 = new Integer(521); 14 | // 调用两个私有的静态方法进行比较判断 15 | equivalentOperator(i1, i2); 16 | equalsFunction(i1, i2); 17 | // 创建两个自定义的 Cartoon 对象 18 | Cartoon c1 = new Cartoon(); 19 | Cartoon c2 = new Cartoon(); 20 | // 为两个 Cartoon 对象赋值 21 | c1.name = c2.name = "Naruto"; 22 | // 调用 equals() 方法进行比较 23 | equalsFunction(c1, c2); 24 | } 25 | 26 | /** 27 | * 通过恒等运算符比较两个对象 28 | * 29 | * @param o1 30 | * @param o2 31 | */ 32 | private static void equivalentOperator(Object o1, Object o2) { 33 | System.out.println(o1 + " == " + o2 + " : " + (o1 == o2)); 34 | System.out.println(o1 + " != " + o2 + " : " + (o1 != o2)); 35 | } 36 | 37 | /** 38 | * 通过 equals() 方法比较两个对象 39 | * 40 | * @param o1 41 | * @param o2 42 | */ 43 | private static void equalsFunction(Object o1, Object o2) { 44 | System.out.println("(" + o1 + ").equals(" + o2 + ") : " + (o1).equals(o2)); 45 | System.out.println("!(" + o1 + ").equals(" + o2 + ") : " + (!(o1).equals(o2))); 46 | } 47 | 48 | 49 | } 50 | 51 | /** 52 | * 自定义卡通类 53 | */ 54 | class Cartoon { 55 | String name; 56 | 57 | /** 58 | * 覆盖 Object 根类中的 hashCode() 方法 59 | * @return 哈希值 60 | */ 61 | @Override 62 | public int hashCode() { 63 | return name.hashCode(); 64 | } 65 | 66 | /** 67 | * 覆盖 Object 根类中的 equals() 方法 68 | * @param o 69 | * @return true or false 70 | */ 71 | @Override 72 | public boolean equals(Object o) { 73 | if (o instanceof Cartoon) { 74 | if (this.name.hashCode() == ((Cartoon) o).name.hashCode()) 75 | return true; 76 | return false; 77 | } else { 78 | return false; 79 | } 80 | } 81 | } 82 | 83 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter4/ForLoop.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter4; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * author:Charies Gavin 7 | * date:2017/12/20,9:43 8 | * https:github.com/guobinhit 9 | * description:测试两种 for 循环方法 10 | */ 11 | public class ForLoop { 12 | public static void main(String[] args) { 13 | // 创建并初始化一个整型数据 14 | int[] arr = new int[]{2, 0, 1, 5, 11, 20}; 15 | 16 | System.out.println("普通的 for 循环方法:"); 17 | 18 | for (int i = 0; i < arr.length; i++) { 19 | System.out.print(arr[i] + " "); 20 | } 21 | 22 | System.out.println(); 23 | System.out.println("高级的 for 循环方法:"); 24 | 25 | for (int i : arr) { 26 | System.out.print(i + " "); 27 | 28 | } 29 | 30 | System.out.println(); 31 | 32 | System.out.println("用 Arrays 的 toString() 方法打印数组:"); 33 | System.out.println(Arrays.toString(arr)); 34 | 35 | // 小心,这里有毒 ~~~ 36 | // doubleForTest(); 37 | } 38 | 39 | /** 40 | * 测试 double 数据类型的 for 循环 41 | */ 42 | private static void doubleForTest() { 43 | for (double x = 0; x != 10; x += 0.1) { 44 | System.out.println(x); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter5/MottoHIT.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter5; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2017/12/25,9:07 6 | * https:github.com/guobinhit 7 | * description:测试 this 关键字 8 | */ 9 | public class MottoHIT { 10 | public static void main(String[] args) { 11 | Hiter hiter_1 = new Hiter(); 12 | Hiter hiter_2 = new Hiter(); 13 | hiter_1.sayMotto("Zora"); 14 | hiter_2.sayMotto("Charies"); 15 | } 16 | } 17 | 18 | class Hiter { 19 | public void sayMotto(String name) { 20 | System.out.println(name + ": 规格严格,功夫到家"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter5/Overload.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter5; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2017/12/22,21:04 6 | * https:github.com/guobinhit 7 | * description:测试方法重载 8 | */ 9 | public class Overload { 10 | public static void main(String[] args) { 11 | introduce(18, "Charies"); 12 | introduce("Charies", 18); 13 | } 14 | 15 | public static void introduce(int age, String name) { 16 | System.out.println("My name is " + name + ", I'm " + age + " old!"); 17 | } 18 | 19 | public static void introduce(String name, int age) { 20 | System.out.println("My name is " + name + ", I'm " + age + " old!"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter5/StructureMethod.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter5; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2017/12/22,20:30 6 | * https:github.com/guobinhit 7 | * description:测试构造方法 8 | */ 9 | public class StructureMethod { 10 | public static void main(String[] args) { 11 | Angel angel_1 = new Angel(); 12 | Angel angel_2 = new Angel("Angela"); 13 | } 14 | } 15 | 16 | class Angel { 17 | /** 18 | * 无参的构造方法 19 | */ 20 | public Angel() { 21 | System.out.println("I'm a angel, but I don't know my name!"); 22 | } 23 | 24 | /** 25 | * 有参的构造方法 26 | * 27 | * @param name 28 | */ 29 | public Angel(String name) { 30 | System.out.println("I'm a angel, my name is " + name + "!"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter5/Zoo.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter5; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2017/12/30,13:40 6 | * https:github.com/guobinhit 7 | * description:测试 this 关键字 8 | */ 9 | public class Zoo { 10 | public Zoo() { 11 | System.out.println("Welcome to CG's Zoo!"); 12 | } 13 | 14 | public static void main(String[] args) { 15 | new Zoo(); 16 | new Animal(); 17 | } 18 | 19 | } 20 | 21 | class Animal { 22 | public Animal() { 23 | /** 24 | * 只能在构造器中用 this 关键字调用对应参数的构造器 25 | */ 26 | this("tiger"); 27 | System.out.println("Animals"); 28 | 29 | //this("panda"); 30 | } 31 | 32 | public Animal(String type) { 33 | System.out.println("This is a " + type); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter7/ClassA.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter7; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2017/12/30,16:22 6 | * https:github.com/guobinhit 7 | * description:测试导出类对象包含子类对象 8 | */ 9 | public class ClassA extends ClassB { 10 | public ClassA() { 11 | System.out.println("==== ClassA extends ClassB =="); 12 | } 13 | 14 | public static void main(String[] args) { 15 | new ClassA(); 16 | } 17 | } 18 | 19 | class ClassB extends ClassC { 20 | public ClassB() { 21 | super("extend show time"); 22 | System.out.println("==== ClassB extends ClassC =="); 23 | } 24 | } 25 | 26 | class ClassC { 27 | public ClassC() { 28 | System.out.println("==== ClassC =="); 29 | } 30 | 31 | public ClassC(String description) { 32 | System.out.println(description); 33 | System.out.println("==== ClassC =="); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter7/FinalParamter.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter7; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2017/12/30,17:34 6 | * https:github.com/guobinhit 7 | * description:测试方法中的 final 参数 8 | */ 9 | public class FinalParamter { 10 | /** 11 | * 无法修改 final 参数所指向的引用 12 | * @param apple 13 | */ 14 | // public void eat(final Apple apple){ 15 | // apple = new Apple(); 16 | // apple.peel(apple); 17 | // } 18 | 19 | public void wash(Apple apple) { 20 | apple = new Apple(); 21 | apple.peel(apple); 22 | } 23 | 24 | /** 25 | * 无法修改 final 参数所指向的引用 26 | * @param i 27 | */ 28 | // public void printNum_1(final int i) { 29 | // System.out.println(i++); 30 | // } 31 | 32 | public void printNum_2(final int j) { 33 | System.out.println(j + 1); 34 | } 35 | 36 | public static void main(String[] args) { 37 | FinalParamter finalParamter = new FinalParamter(); 38 | finalParamter.wash(null); 39 | finalParamter.printNum_2(5); 40 | } 41 | } 42 | 43 | class Apple { 44 | public void peel(Apple apple) { 45 | System.out.println("Apple apple, peel apple..."); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter8/CovariantReturnType.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter8; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/1/4,22:10 6 | * https:github.com/guobinhit 7 | * description:测试协变返回类型 8 | */ 9 | public class CovariantReturnType { 10 | public static void main(String[] args) { 11 | Flower flower = new Flower(); 12 | Plant plant = flower.kind(); 13 | System.out.println("未使用协变返回类型:" + plant); 14 | // 使用协变返回类型 15 | flower = new Luoyangred(); 16 | plant = flower.kind(); 17 | System.out.println("使用协变返回类型后:" + plant); 18 | } 19 | } 20 | 21 | /** 22 | * 植物基类 23 | */ 24 | class Plant { 25 | public String toString() { 26 | return "Plant"; 27 | } 28 | } 29 | 30 | /** 31 | * 牡丹花,继承自植物基类 32 | */ 33 | class Peony extends Plant { 34 | public String toString() { 35 | return "Peony"; 36 | } 37 | } 38 | 39 | /** 40 | * 花 41 | */ 42 | class Flower { 43 | Plant kind() { 44 | return new Plant(); 45 | } 46 | } 47 | 48 | /** 49 | * 洛阳红,十大贵品牡丹花之一 50 | */ 51 | class Luoyangred extends Flower { 52 | Peony kind() { 53 | return new Peony(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter8/PrivateOverride.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter8; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/1/3,8:55 6 | * https:github.com/guobinhit 7 | * description:测试私有方法是否能被覆盖 8 | */ 9 | public class PrivateOverride { 10 | private void test_1() { 11 | System.out.println("私有方法能被覆盖吗?答案:不能。"); 12 | } 13 | 14 | public void test_2() { 15 | System.out.println("公有方法能被覆盖吗?答案:能。"); 16 | } 17 | 18 | public static void main(String[] args) { 19 | PrivateOverride po = new DerivedOverride(); 20 | po.test_1(); 21 | po.test_2(); 22 | } 23 | } 24 | 25 | class DerivedOverride extends PrivateOverride { 26 | public void test_1() { 27 | System.out.println("Oh, my god, 我们成功覆盖了私有方法!"); 28 | } 29 | 30 | public void test_2() { 31 | System.out.println("Hi, buddy, 我们成功覆盖了公有方法!"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter9/ClassInInterface.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter9; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/4,10:50 6 | * https:github.com/guobinhit 7 | * description:在接口内部定义内部类 8 | */ 9 | public interface ClassInInterface { 10 | void interfaceMethod(); 11 | 12 | class InnerClassInInterface { 13 | void sayHello() { 14 | System.out.println("Hello World!"); 15 | } 16 | 17 | public static void main(String[] args) { 18 | new InnerClassInInterface().sayHello(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter9/InheritInnerClass.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter9; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/4,11:28 6 | * https:github.com/guobinhit 7 | * description:继承内部类 8 | */ 9 | class ContainInner { 10 | class Inner { 11 | public void sayName() { 12 | // 获取类名 13 | System.out.println("调用此方法的类名为:" + this.getClass().getSimpleName()); 14 | } 15 | } 16 | } 17 | 18 | public class InheritInnerClass extends ContainInner.Inner { 19 | /** 20 | * 继承内部类,必须调用含参构造器,且参数类型为外部类类型 21 | * 22 | * @param ci 23 | */ 24 | InheritInnerClass(ContainInner ci) { 25 | // 必须显示调用外部类构造器 26 | ci.super(); 27 | } 28 | 29 | public static void main(String[] args) { 30 | ContainInner ci = new ContainInner(); 31 | InheritInnerClass iic = new InheritInnerClass(ci); 32 | iic.sayName(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter9/NestInterface.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter9; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/1,9:03 6 | * https:github.com/guobinhit 7 | * description:测试类中嵌套接口 8 | */ 9 | public class NestInterface { 10 | /** 11 | * 嵌套在类内部的接口 12 | */ 13 | interface InterfaceA { 14 | void methodA(); 15 | } 16 | 17 | /** 18 | * 实现接口,并用 public 修饰 19 | */ 20 | public class NestB implements InterfaceA { 21 | 22 | @Override 23 | public void methodA() { 24 | System.out.println("public class NestB implements InterfaceA"); 25 | } 26 | } 27 | 28 | /** 29 | * 实现接口,并用 private 修饰 30 | */ 31 | private class NestC implements InterfaceA { 32 | 33 | @Override 34 | public void methodA() { 35 | System.out.println("private class NestC implements InterfaceA"); 36 | } 37 | } 38 | 39 | /** 40 | * 获取 NestB 的实例方法 41 | * 42 | * @return NestB 43 | */ 44 | public NestB getNestB() { 45 | return new NestB(); 46 | } 47 | 48 | /** 49 | * 获取 NestC 的实例方法 50 | * 51 | * @return NestC 52 | */ 53 | public NestC getNestC() { 54 | return new NestC(); 55 | } 56 | 57 | public static void main(String[] args) { 58 | NestInterface ni = new NestInterface(); 59 | NestB nestB = ni.getNestB(); 60 | NestC nestC = ni.getNestC(); 61 | nestB.methodA(); 62 | nestC.methodA(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/thought/chapter9/OuterInterface.java: -------------------------------------------------------------------------------- 1 | package com.hit.thought.chapter9; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/3/1,9:23 6 | * https:github.com/guobinhit 7 | * description:测试接口中嵌套接口 8 | */ 9 | public interface OuterInterface { 10 | /** 11 | * 在接口内部定义接口 A 12 | */ 13 | interface InnerInterfaceA { 14 | void methodInnerInterfaceA(); 15 | } 16 | 17 | /** 18 | * 在接口内部定义接口 B 19 | */ 20 | interface InnerInterfaceB { 21 | void methodInnerInterfaceB(); 22 | } 23 | 24 | /** 25 | * 定义外部接口方法 26 | */ 27 | void methodOuterInterface(); 28 | } 29 | 30 | /** 31 | * 直接实现外部接口,仅需要实现外部接口定义的方法,并不需要实现外部接口内定义的内部接口的方法 32 | */ 33 | class ImplOuterInterface implements OuterInterface { 34 | 35 | @Override 36 | public void methodOuterInterface() { 37 | System.out.println("Overrider OuterInterface method!"); 38 | } 39 | } 40 | 41 | /** 42 | * 我们也可以指定实现某接口内部定义的内部接口 43 | */ 44 | class ImplInnerInterface implements OuterInterface.InnerInterfaceA, OuterInterface.InnerInterfaceB { 45 | 46 | @Override 47 | public void methodInnerInterfaceA() { 48 | System.out.println("Overrider OuterInterface.InnerInterfaceA method!"); 49 | } 50 | 51 | @Override 52 | public void methodInnerInterfaceB() { 53 | System.out.println("Overrider OuterInterface.InnerInterfaceB method!"); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/vmachine/chapter1/DirectMemoryOOM.java: -------------------------------------------------------------------------------- 1 | package com.hit.vmachine.chapter1; 2 | 3 | import sun.misc.Unsafe; 4 | 5 | import java.lang.reflect.Field; 6 | 7 | /** 8 | * author:Charies Gavin 9 | * date:2018/8/05,17:26 10 | * https:github.com/guobinhit 11 | * description:测试本机直接内测溢出 12 | * VM Args: -Xmx20m -XX:DirectMemorySize=10m 13 | */ 14 | public class DirectMemoryOOM { 15 | private static final int _1MB = 1024 * 1024; 16 | 17 | public static void main(String[] args) throws Exception { 18 | Field unsafeField = Unsafe.class.getDeclaredFields()[0]; 19 | unsafeField.setAccessible(true); 20 | Unsafe unsafe = (Unsafe) unsafeField.get(null); 21 | while (true) { 22 | unsafe.allocateMemory(_1MB); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/vmachine/chapter1/HeapOOM.java: -------------------------------------------------------------------------------- 1 | package com.hit.vmachine.chapter1; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * author:Charies Gavin 8 | * date:2018/8/05,15:30 9 | * https:github.com/guobinhit 10 | * description:测试 Java 堆溢出 11 | * VM Args: -Xms20m -Xmx30m -XX:+HeapDumpOnOutOfMemoryError 12 | */ 13 | public class HeapOOM { 14 | static class OOMObject { 15 | } 16 | 17 | public static void main(String[] args) { 18 | List list = new ArrayList(); 19 | // 无限循环,直至发生 OOM 为止 20 | while (true) { 21 | list.add(new OOMObject()); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/vmachine/chapter1/JavaVMStackOOM.java: -------------------------------------------------------------------------------- 1 | package com.hit.vmachine.chapter1; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/8/05,17:04 6 | * https:github.com/guobinhit 7 | * description:测试虚拟机栈和本地方法栈溢出 8 | * VM Args: -Xss2m 9 | */ 10 | public class JavaVMStackOOM { 11 | private void dontStop() { 12 | while (true) { 13 | } 14 | } 15 | 16 | public void stackLeakByThread() { 17 | while (true) { 18 | Thread thread = new Thread(new Runnable() { 19 | @Override 20 | public void run() { 21 | dontStop(); 22 | } 23 | }); 24 | thread.start(); 25 | } 26 | } 27 | 28 | public static void main(String[] args) { 29 | JavaVMStackOOM oom = new JavaVMStackOOM(); 30 | oom.stackLeakByThread(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/vmachine/chapter1/JavaVMStackSOF.java: -------------------------------------------------------------------------------- 1 | package com.hit.vmachine.chapter1; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/8/05,16:59 6 | * https:github.com/guobinhit 7 | * description:测试虚拟机栈和本地方法栈溢出 8 | * VM Args: -Xss128k 9 | */ 10 | public class JavaVMStackSOF { 11 | private int stackLength = 1; 12 | 13 | // 循环调用 14 | public void stackLeak() { 15 | stackLength++; 16 | stackLeak(); 17 | } 18 | 19 | public static void main(String[] args) throws Throwable { 20 | JavaVMStackSOF sof = new JavaVMStackSOF(); 21 | try { 22 | sof.stackLeak(); 23 | } catch (Throwable e) { 24 | System.out.println("stack length: " + sof.stackLength); 25 | throw e; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/vmachine/chapter1/RuntimeConstantPoolOOM.java: -------------------------------------------------------------------------------- 1 | package com.hit.vmachine.chapter1; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * author:Charies Gavin 8 | * date:2018/8/05,17:14 9 | * https:github.com/guobinhit 10 | * description:测试方法区和运行时常量池溢出 11 | * VM Args: -XX:PermSize=10m -XX:MaxPermSize=10m 12 | */ 13 | public class RuntimeConstantPoolOOM { 14 | public static void main(String[] args) { 15 | // 使用 List 保持着常量池引用,避免 Full GC 回收常量池行为 16 | List list = new ArrayList(); 17 | // 10MB 的 PermSize 在 integer 范围内足够产生 OOM 了 18 | int i = 0; 19 | while (true) { 20 | list.add(String.valueOf(i++).intern()); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /javaskills/src/com/hit/vmachine/chapter2/ReferenceCountingGC.java: -------------------------------------------------------------------------------- 1 | package com.hit.vmachine.chapter2; 2 | 3 | /** 4 | * author:Charies Gavin 5 | * date:2018/8/26,16:59 6 | * https:github.com/guobinhit 7 | * description:引用计数算法 8 | */ 9 | public class ReferenceCountingGC { 10 | public Object instance = null; 11 | private static final int _1MB = 1024 * 1024; 12 | 13 | /** 14 | * 该成员属性的唯一意义就是占点内存,以便能在 GC 日志中看清楚是否被回收过 15 | */ 16 | private byte[] bigSize = new byte[2 * _1MB]; 17 | 18 | public static void main(String[] args) { 19 | ReferenceCountingGC objA = new ReferenceCountingGC(); 20 | ReferenceCountingGC objB = new ReferenceCountingGC(); 21 | objA.instance = objB; 22 | objB.instance = objA; 23 | 24 | objA = null; 25 | objB = null; 26 | 27 | /** 28 | * 假设在这行发生 GC,objA 和 objB 是否能被回收? 29 | */ 30 | System.gc(); 31 | } 32 | } 33 | --------------------------------------------------------------------------------