├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── kotlin-in-action ├── .gitignore ├── build.gradle └── src │ └── main │ └── java │ ├── annotation │ ├── AnnotationInstance.kt │ ├── AnnotationLambda.kt │ ├── AnnotationParameter.kt │ ├── AnnotationTest.kt │ ├── AnnotationUseSite.kt │ ├── JavaBean.java │ ├── Person.kt │ ├── custom │ │ ├── AnnotationInstance.kt │ │ ├── FieldOnly.kt │ │ ├── JsonName.kt │ │ ├── JsonName2.kt │ │ ├── JsonName3.kt │ │ ├── JvmRecordTest.kt │ │ ├── MethodOnly.kt │ │ ├── Normal.kt │ │ ├── Parameter.kt │ │ ├── PropertyGetterOnly.kt │ │ ├── PropertyOnly.kt │ │ └── Tag.kt │ ├── java_repeatable │ │ ├── Main.java │ │ ├── Schedule.java │ │ └── Schedules.java │ └── kotlin_annoation │ │ ├── DeprecatedTest.kt │ │ ├── JvmFieldTest.kt │ │ ├── JvmNameTest.java │ │ ├── JvmNameTest.kt │ │ ├── JvmStaticTest.kt │ │ ├── JvmStaticTestInJava.java │ │ └── SuppressTest.kt │ ├── base │ ├── AlsoTest.kt │ ├── AnonymousFunctions.kt │ ├── CompareTest.java │ ├── CompareTest.kt │ ├── ExceptionTest.java │ ├── ExceptionTest.kt │ ├── ExtensionFuncTest.kt │ ├── ExtensionProperty.kt │ ├── FunctionVarargs.java │ ├── FunctionVarargs.kt │ ├── InFixFunction.kt │ ├── LambdaReturnValue.kt │ ├── LetTest.kt │ ├── LoopTest.kt │ ├── NothingTest.kt │ ├── OperatorTest.kt │ ├── RunTest.kt │ ├── SpreadOperatorTest.kt │ ├── StringTest.java │ ├── StringTest.kt │ ├── TopLevelTest.kt │ └── WhenTest.kt │ ├── collection │ ├── AllAnyCountFindGroupByTest.kt │ ├── CollectionCreateTest.kt │ ├── CollectionNullabilityTest.kt │ ├── FilterMapTest.kt │ ├── FlatMapFlattenTest.kt │ ├── ImpJavaInterfaceWhenCollection.kt │ ├── LazyCollectionTest.kt │ └── ListJava.java │ ├── data_type │ ├── NothingTypeTest.kt │ ├── NumberConversion.kt │ ├── NumberTypeTest.kt │ ├── UnitTypeTest.kt │ └── VoidTypeTest.java │ ├── delegated │ ├── DelegatedPropertyBy.kt │ ├── DelegatedPropertyByLazy.kt │ ├── DelegatedPropertyByMap.kt │ ├── DelegatedPropertyLazyMode.kt │ ├── DelegatedPropertyListenerImp.kt │ └── DelegationPattern.kt │ ├── generic │ ├── GenericReified.kt │ ├── GenericVariance.kt │ ├── MyList.kt │ └── java_generic │ │ ├── JavaGenericWildcardTest.java │ │ ├── bean │ │ ├── Apple.java │ │ ├── Food.java │ │ ├── Fruit.java │ │ ├── Pear.java │ │ └── Plate.java │ │ └── res │ │ ├── generic_extends.png │ │ └── generic_super.png │ ├── higher_order_function │ ├── ControlFlowInHighOrderFunc.kt │ ├── FunctionTypeWithReceiver.kt │ ├── HigherOrderFunc.kt │ ├── InlineFunction.kt │ ├── LambdaReceiverChangeTest.kt │ ├── ScopeFunctions.kt │ └── UsingFuncInJava.java │ ├── inline │ └── InlineTest.kt │ ├── lambda │ ├── Button.java │ ├── FunctionalInterface.java │ ├── FunctionalInterfaceTest.kt │ ├── FunctionalInterfaceTest2.kt │ ├── JavaLambdaModifyVariable.java │ ├── KotlinInterface.kt │ ├── KotlinLambdaModifyVariable.kt │ ├── LambdaAsParameter.kt │ ├── LambdaToVariableTest.kt │ ├── LambdaWithReceiver.kt │ ├── MemberReferenceTest.kt │ └── Person.kt │ ├── new_class │ ├── ClassCreate.kt │ ├── ClassPrimaryConstructor.kt │ ├── ClassPrimaryConstructor2.kt │ ├── ClassPrimaryConstructor3.kt │ ├── ClassSecondaryConstructor.kt │ ├── ClassSecondaryConstructorKt2.kt │ ├── Color.kt │ ├── DataClassTest.kt │ ├── InitBlock.kt │ ├── InnerClassTest.kt │ ├── InterfaceTest.kt │ ├── Java8InterfaceMethod.java │ ├── SealedClassTest.kt │ ├── SingletonTest.kt │ └── Test.java │ ├── nullability │ ├── KotlinJavaNullability.kt │ ├── LateInitTest.kt │ ├── NullabilityBasic.kt │ ├── NullabilityExtensionFunc.kt │ ├── User.kt │ ├── UserPresenter.java │ └── UserView.kt │ ├── object_keyword │ ├── ObjectKeywordTest.kt │ ├── ObjectKeywordTest2.kt │ ├── ObjectKeywordTest3.kt │ ├── ObjectKeywordTest4.kt │ ├── ObjectKeywordTest5.kt │ └── ObjectKeywordTest6.kt │ ├── operator_overloading │ ├── ArithmeticOperator.kt │ ├── ComparisonOperator.kt │ ├── ComponentOprerator.kt │ ├── CompoundAssignmentOperator.kt │ ├── InOperator.kt │ ├── IndexOpertaor.kt │ ├── Person.kt │ ├── Point.kt │ ├── RangeToOperator.kt │ └── UnaryOperator.kt │ ├── reflection │ ├── Book.kt │ ├── MemberReferenceTest.kt │ ├── ORM_Test.kt │ ├── ReflectionBasic.kt │ └── framework │ │ ├── Dao.kt │ │ ├── IDao.kt │ │ └── annotations │ │ ├── Field.kt │ │ ├── ID.kt │ │ └── Table.kt │ ├── strings │ └── StringUtils.kt │ ├── test │ ├── CompanionTest.kt │ ├── InternalClassTest.kt │ ├── JavaDefaultClassTest.java │ ├── MemberModifierJavaTest.java │ └── MemberModifierTest.kt │ ├── tutorials │ ├── lesson04 │ │ ├── JavaSwitchTest.java │ │ ├── Main.kt │ │ └── README.md │ ├── lesson05 │ │ ├── Main.kt │ │ └── README.md │ ├── lesson06 │ │ ├── Main.kt │ │ └── README.md │ ├── lesson07 │ │ ├── Main.java │ │ ├── Main.kt │ │ └── README.md │ ├── lesson08 │ │ ├── Main.kt │ │ └── README.md │ ├── lesson09 │ │ └── Main.kt │ ├── lesson10 │ │ ├── JavaCompareString.java │ │ └── Main.kt │ ├── lesson11 │ │ ├── ClassMethod.kt │ │ ├── Java.java │ │ ├── Main.kt │ │ ├── README.md │ │ └── Top.kt │ ├── lesson12 │ │ └── README.md │ ├── lesson13 │ │ ├── Introspection.java │ │ └── PF.java │ ├── lesson14 │ │ ├── LateinitTest.kt │ │ ├── Main.kt │ │ ├── PropertyTest.kt │ │ ├── README.md │ │ └── TEST.java │ ├── lesson15 │ │ └── REAMD.md │ ├── lesson16 │ │ └── README.md │ ├── lesson17 │ │ └── README.md │ ├── lesson18 │ │ ├── Main.kt │ │ ├── README.md │ │ ├── WithoutEnum.kt │ │ └── WithoutEnum2.kt │ ├── lesson23 │ │ ├── Main.kt │ │ ├── NonSealedClass.kt │ │ └── README.md │ ├── lesson24 │ │ └── README.md │ ├── lesson25 │ │ ├── Main.java │ │ ├── Main.kt │ │ ├── README.md │ │ └── file.txt │ ├── lesson26 │ │ ├── JavaException.java │ │ ├── KtException.kt │ │ └── README.md │ ├── lesson27 │ │ ├── JavaAbusedCheckedException.java │ │ ├── KtDesignExceptionApi.kt │ │ ├── README.md │ │ ├── ThrowsTest.java │ │ └── UncaughtExceptionHandlerTest.java │ ├── lesson28 │ │ └── README.md │ ├── lesson29 │ │ ├── Main.kt │ │ └── README.md │ ├── lesson30 │ │ └── README.md │ ├── lesson31 │ │ └── README.md │ ├── lesson32 │ │ └── Main.kt │ └── lesson33 │ │ └── Main.kt │ └── visibility_modifier │ ├── README.md │ ├── modifier_class │ ├── InternalClass.kt │ ├── PrivateClass.kt │ ├── PublicClass.kt │ ├── default_ │ │ ├── JavaDefaultClass.java │ │ └── JavaDefaultClassTest.java │ └── protect │ │ ├── ExtendJavaProtectedClass.java │ │ ├── ExtendKotlinProtectedClass.kt │ │ ├── JavaProtectedClass.java │ │ ├── ProtectedClassTest.kt │ │ └── ProtectedTopClass.java │ └── modifier_member │ ├── MemberModifier.kt │ ├── MemberModifierJava.java │ ├── MemberModifierJavaTest.java │ └── MemberModifierTest.kt ├── other-module ├── .gitignore ├── build.gradle └── src │ └── main │ └── java │ └── visibility_modifier │ ├── GetInternalClass.kt │ └── MemberModifierTest.kt ├── settings.gradle └── src └── main └── kotlin └── Main.kt /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | !**/src/main/**/build/ 5 | !**/src/test/**/build/ 6 | 7 | ### IntelliJ IDEA ### 8 | .idea/ 9 | *.iws 10 | *.iml 11 | *.ipr 12 | out/ 13 | !**/src/main/**/out/ 14 | !**/src/test/**/out/ 15 | 16 | ### Eclipse ### 17 | .apt_generated 18 | .classpath 19 | .factorypath 20 | .project 21 | .settings 22 | .springBeans 23 | .sts4-cache 24 | bin/ 25 | !**/src/main/**/bin/ 26 | !**/src/test/**/bin/ 27 | 28 | ### NetBeans ### 29 | /nbproject/private/ 30 | /nbbuild/ 31 | /dist/ 32 | /nbdist/ 33 | /.nb-gradle/ 34 | 35 | ### VS Code ### 36 | .vscode/ 37 | 38 | ### Mac OS ### 39 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## KotlinTutorials 2 | 3 | 4 | 我的《Kotlin入门到进阶》视频教程: 5 | 6 | - [x] [Kotlin入门到进阶(1)——前言](https://www.bilibili.com/video/BV1hR4y1A7Vu/) 7 | - [x] [Kotlin入门到进阶(2)——变量、函数入门](https://www.bilibili.com/video/BV1Ur4y1t7a3/) 8 | - [x] [Kotlin入门到进阶(3)——表达式、语句及与 Java 的对比](https://www.bilibili.com/video/BV1r54y1f7gT/) 9 | - [x] [Kotlin入门到进阶(4)——结构化编程:顺序结构、选择结构、循环结构](https://www.bilibili.com/video/BV1bu41167Dr/) 10 | - [x] [Kotlin入门到进阶(5)——空安全(Null Safety)和实战技巧](https://www.bilibili.com/video/BV1AY4y1t7hX/) 11 | - [x] [Kotlin入门到进阶(6)——类型系统和访问修饰符详解](https://www.bilibili.com/video/BV18Y4y1z7h8/) 12 | - [x] [Kotlin入门到进阶(7)——数组类型和它的扩展函数](https://www.bilibili.com/video/BV1RB4y1y7bU/) 13 | - [x] [Kotlin入门到进阶(8)——Nothing 类型, 不为人知的细节](https://www.bilibili.com/video/BV1SR4y1c7Xm/) 14 | - [x] [Kotlin入门到进阶(9)——深入理解 Kotlin 集合、序列](https://www.bilibili.com/video/BV1o54y1Z7s3/) 15 | - [x] [Kotlin入门到进阶(10)——聊一聊 Kotlin String](https://www.bilibili.com/video/BV1z3411G7gA/) 16 | - [x] [Kotlin入门到进阶(11)——再谈 Kotlin 函数](https://www.bilibili.com/video/BV13F411j7mF/) 17 | - [x] [Kotlin入门到进阶(12)——彻底搞懂 Class 和 Interface](https://www.bilibili.com/video/BV1ev4y1A7kM/) 18 | - [x] [Kotlin入门到进阶(13)——搞懂 Java Property 和 Field 的区别](https://www.bilibili.com/video/BV1At4y1s7sE/) 19 | - [x] [Kotlin入门到进阶(14)——lateinit property 案例实战](https://www.bilibili.com/video/BV1CY4y1678g/) 20 | - [x] [Kotlin入门到进阶(15)——深入理解属性代理(一) by lazy、Delegates.observable](https://www.bilibili.com/video/BV1j3411V7Ve/) 21 | - [x] [Kotlin入门到进阶(16)——深入理解属性委托(二) 代码演示 LazyThreadSafetyMode 的区别](https://www.bilibili.com/video/BV18Z4y147b2/) 22 | - [x] [Kotlin入门到进阶(17)——深入理解属性委托(三) by map 和委托模式](https://www.bilibili.com/video/BV1at4y1p7iB/) 23 | - [x] [Kotlin入门到进阶(18)——枚举(一)为什么要有枚举?](https://www.bilibili.com/video/BV1it4y1p7TA/) 24 | - [x] [Kotlin入门到进阶(19)——枚举(二)枚举 API 特性](https://www.bilibili.com/video/BV1jU4y117Q9/) 25 | - [x] [Kotlin入门到进阶(20)——枚举(三)枚举的本质](https://www.bilibili.com/video/BV1W3411G7n9/) 26 | - [x] [Kotlin入门到进阶(21)——枚举(四)枚举 switch case 原理分析](https://www.bilibili.com/video/BV1SS4y1v7Pm/) 27 | - [x] [Kotlin入门到进阶(22)——枚举(五)枚举的最佳实践](https://www.bilibili.com/video/BV1oY411T7d2/) 28 | - [x] [Kotlin入门到进阶(23)——Kotlin1.7 枚举、密封类新特性解读 & 枚举 VS 密封类](https://www.bilibili.com/video/BV1vZ4y1t7Gr/) 29 | - [x] [Kotlin入门到进阶(24)——操作符重载全解](https://www.bilibili.com/video/BV1LZ4y1q7hE/) 30 | - [x] [Kotlin入门到进阶(25)——优雅的文件 I/O 操作](https://www.bilibili.com/video/BV1Jt4y1H7ru/) 31 | - [x] [Kotlin入门到进阶(26)——异常(一) Kotlin 异常与 Java 的异同](https://www.bilibili.com/video/BV1SY4y1W76G/) 32 | - [x] [Kotlin入门到进阶(27)——异常(二) Kotlin异常设计理念、如何设计异常API](https://www.bilibili.com/video/BV1A3411u7UB/) 33 | - [x] [Kotlin入门到进阶(28)——注解](https://www.bilibili.com/video/BV1c3411w77q) 34 | - [x] [Kotlin入门到进阶(29)——深入理解反射](https://www.bilibili.com/video/BV13Y4y1n7X7/) 35 | - [x] [Kotlin入门到进阶(30)——深入理解 lambda 表达式](https://www.bilibili.com/video/BV1L34y1p7ax/) 36 | - [x] [Kotlin入门到进阶(31)——彻底搞懂高阶函数](https://www.bilibili.com/video/BV13T411g714/) 37 | - [x] [Kotlin入门到进阶(32)——inline、crossinline、noinline 解析](https://www.bilibili.com/video/BV1Kj41127p9/) 38 | - [ ] [Kotlin入门到进阶(33)——return 和 loop jump](https://www.bilibili.com/video/BV1oj411y7x9/) 39 | - [ ] 泛型 40 | - [ ] 协程 41 | - [ ] Kotlin 和 Java 交互的一些问题 42 | 43 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.jetbrains.kotlin.jvm' version '1.8.21' 3 | id 'application' 4 | } 5 | 6 | group = 'org.example' 7 | version = '1.0-SNAPSHOT' 8 | 9 | repositories { 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | testImplementation 'org.jetbrains.kotlin:kotlin-test' 15 | implementation project(":kotlin-in-action") 16 | } 17 | 18 | test { 19 | useJUnitPlatform() 20 | } 21 | 22 | kotlin { 23 | jvmToolchain(11) 24 | } 25 | 26 | application { 27 | mainClassName = 'MainKt' 28 | } 29 | 30 | tasks.withType(JavaCompile).configureEach { 31 | options.encoding = 'UTF-8' 32 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | kotlin.code.style=official 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chiclaim/KotlinTutorials/1048a734514e300d6050fb3da1f0bd11c0f3be4d/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /kotlin-in-action/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | !**/src/main/**/build/ 5 | !**/src/test/**/build/ 6 | 7 | ### IntelliJ IDEA ### 8 | .idea/modules.xml 9 | .idea/jarRepositories.xml 10 | .idea/compiler.xml 11 | .idea/libraries/ 12 | *.iws 13 | *.iml 14 | *.ipr 15 | out/ 16 | !**/src/main/**/out/ 17 | !**/src/test/**/out/ 18 | 19 | ### Eclipse ### 20 | .apt_generated 21 | .classpath 22 | .factorypath 23 | .project 24 | .settings 25 | .springBeans 26 | .sts4-cache 27 | bin/ 28 | !**/src/main/**/bin/ 29 | !**/src/test/**/bin/ 30 | 31 | ### NetBeans ### 32 | /nbproject/private/ 33 | /nbbuild/ 34 | /dist/ 35 | /nbdist/ 36 | /.nb-gradle/ 37 | 38 | ### VS Code ### 39 | .vscode/ 40 | 41 | ### Mac OS ### 42 | .DS_Store -------------------------------------------------------------------------------- /kotlin-in-action/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'org.jetbrains.kotlin.jvm' version '1.8.21' 4 | } 5 | 6 | group = 'org.example' 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | testImplementation platform('org.junit:junit-bom:5.9.1') 14 | testImplementation 'org.junit.jupiter:junit-jupiter' 15 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" 16 | implementation "org.jetbrains.kotlin:kotlin-reflect" 17 | } 18 | 19 | test { 20 | useJUnitPlatform() 21 | } 22 | kotlin { 23 | jvmToolchain(11) 24 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/AnnotationInstance.kt: -------------------------------------------------------------------------------- 1 | package annotation 2 | 3 | import annotation.custom.AnnotationInstance 4 | import kotlin.concurrent.thread 5 | 6 | /** 7 | * 8 | * @author kumushuoshuo 9 | * @github https://github.com/chiclaim/ 10 | */ 11 | 12 | 13 | fun main(){ 14 | fun test(annotationInstance: AnnotationInstance){ 15 | 16 | } 17 | // 可以直接构造注解的实例 18 | test(AnnotationInstance()) 19 | 20 | thread { 21 | 22 | } 23 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/AnnotationLambda.kt: -------------------------------------------------------------------------------- 1 | package annotation 2 | 3 | import kotlin.concurrent.thread 4 | 5 | annotation class AnnotationLambda 6 | 7 | 8 | fun main() { 9 | // 在 lambda 上使用注解 10 | thread @AnnotationLambda{ 11 | 12 | } 13 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/AnnotationParameter.kt: -------------------------------------------------------------------------------- 1 | package annotation 2 | 3 | import kotlin.reflect.KClass 4 | 5 | /** 6 | * Desc: 7 | * Created by Chiclaim on 2018/10/15. 8 | */ 9 | interface Company { 10 | val name: 11 | String 12 | } 13 | 14 | data class CompanyImpl(override val name: String) : Company 15 | data class Employee( 16 | val name: String, 17 | @DeserializeInterface(CompanyImpl::class) val company: Company 18 | ) 19 | 20 | @Target(AnnotationTarget.PROPERTY) 21 | annotation class DeserializeInterface(val targetClass: KClass) -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/AnnotationTest.kt: -------------------------------------------------------------------------------- 1 | package annotation 2 | 3 | /** 4 | * Desc: 5 | * Created by Chiclaim on 2018/10/15. 6 | */ 7 | 8 | //1,@PropertyOnly Kotlin定义的Property不能使用到Java属性上,可以使用AnnotationTarget.FIELD 9 | //2,在Java中注解默认保留到class字节码级别,Kotlin默认是Runtime运行时 10 | //3,Kotlin注解不能包含函数 11 | 12 | 13 | @Deprecated("Use removeAt(index) instead.", ReplaceWith("removeAt(index)")) 14 | fun remove(index: Int) { 15 | } 16 | 17 | 18 | fun main(args: Array) { 19 | remove(0) 20 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/AnnotationUseSite.kt: -------------------------------------------------------------------------------- 1 | package annotation 2 | 3 | import annotation.custom.Parameter 4 | import annotation.custom.FieldOnly 5 | import annotation.custom.Normal 6 | import annotation.custom.PropertyGetterOnly 7 | 8 | /** 9 | * 10 | * @author kumushuoshuo 11 | * @github https://github.com/chiclaim/ 12 | */ 13 | class AnnotationUseSite(@field:FieldOnly val name:String, // annotate Java field 14 | @get:PropertyGetterOnly val age:Int, // annotate Java getter 15 | @param:Parameter val sex:Int) { // annotate Java constructor parameter 16 | 17 | @property:Normal 18 | @setparam:Normal 19 | var address:String? = null 20 | 21 | @delegate:Normal 22 | val phone:String by lazy { 23 | "10086" 24 | } 25 | 26 | // 不指定 use-site 27 | @UnknownUseSite 28 | var city:String?=null 29 | } 30 | 31 | fun @receiver:Normal AnnotationUseSite.printInfo(){ 32 | println("${this.name},${this.address}") 33 | } 34 | 35 | val @receiver:Normal AnnotationUseSite.email:String 36 | get() { 37 | return "chiclaim@gmail.com" 38 | } 39 | 40 | // 如果你不指定 use-site,kotlin 会根据注解的 AnnotationTarget 来确定 use-site target 41 | // 如果 AnnotationTarget 指定了多个值,那么 target 会按照 param/property/field 顺序来匹配。 42 | 43 | @Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY) 44 | annotation class UnknownUseSite 45 | 46 | 47 | 48 | /* 49 | The full list of supported use-site targets is: 50 | 51 | file 52 | 53 | property (annotations with this target are not visible to Java) 54 | 55 | field 56 | 57 | get (property getter) 58 | 59 | set (property setter) 60 | 61 | receiver (receiver parameter of an extension function or property) 62 | 63 | param (constructor parameter) 64 | 65 | setparam (property setter parameter) 66 | 67 | delegate (the field storing the delegate instance for a delegated property) 68 | 69 | 70 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/JavaBean.java: -------------------------------------------------------------------------------- 1 | package annotation; 2 | 3 | import annotation.custom.FieldOnly; 4 | import annotation.custom.PropertyGetterOnly; 5 | 6 | /** 7 | * Desc: 8 | * Created by Chiclaim on 2018/10/15. 9 | */ 10 | public class JavaBean { 11 | // @PropertyOnly Kotlin 定义的 Property 注解不能使用到 Java 字段上,可以使用AnnotationTarget.FIELD 12 | // 关于 Java 的 属性和字段的区别可以查看第 lesson13 13 | private String id; 14 | 15 | @FieldOnly 16 | private String name; 17 | 18 | // @PropertyOnly 编译器报错 error 19 | @PropertyGetterOnly 20 | public String getName() { 21 | return name; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/Person.kt: -------------------------------------------------------------------------------- 1 | package annotation 2 | 3 | import annotation.custom.* 4 | 5 | /** 6 | * Desc: 7 | * Created by Chiclaim on 2018/10/15. 8 | */ 9 | class Person { 10 | 11 | @JsonName 12 | var firstName: String? = null 13 | 14 | @JsonName2("lastName") 15 | var lastName: String? = null 16 | 17 | @JsonName2(name = "email") 18 | var email: String? = null 19 | 20 | @JsonName3("sex", "male") 21 | var gender: String? = null 22 | 23 | @PropertyOnly 24 | private var adress: String? = null 25 | 26 | @MethodOnly 27 | fun run() { 28 | println("run...") 29 | } 30 | 31 | 32 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/custom/AnnotationInstance.kt: -------------------------------------------------------------------------------- 1 | package annotation.custom 2 | 3 | annotation class AnnotationInstance 4 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/custom/FieldOnly.kt: -------------------------------------------------------------------------------- 1 | package annotation.custom 2 | 3 | /** 4 | * Desc: 5 | * Created by Chiclaim on 2018/10/15. 6 | */ 7 | @Target(AnnotationTarget.FIELD) 8 | annotation class FieldOnly -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/custom/JsonName.kt: -------------------------------------------------------------------------------- 1 | package annotation.custom 2 | 3 | /** 4 | * Desc: 5 | * Created by Chiclaim on 2018/10/15. 6 | */ 7 | annotation class JsonName -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/custom/JsonName2.kt: -------------------------------------------------------------------------------- 1 | package annotation.custom 2 | 3 | /** 4 | * Desc: 5 | * Created by Chiclaim on 2018/10/15. 6 | */ 7 | annotation class JsonName2(val name: String) -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/custom/JsonName3.kt: -------------------------------------------------------------------------------- 1 | package annotation.custom 2 | 3 | /** 4 | * Desc: 5 | * Created by Chiclaim on 2018/10/15. 6 | */ 7 | annotation class JsonName3(val name: String, val value: String) -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/custom/JvmRecordTest.kt: -------------------------------------------------------------------------------- 1 | package annotation.custom 2 | 3 | /** 4 | * 5 | * @author kumushuoshuo 6 | * @github https://github.com/chiclaim/ 7 | */ 8 | //@JvmRecord JDK15 才有 record 的语法 9 | class JvmRecordTest { 10 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/custom/MethodOnly.kt: -------------------------------------------------------------------------------- 1 | package annotation.custom 2 | 3 | /** 4 | * Desc: 5 | * Created by Chiclaim on 2018/10/15. 6 | */ 7 | @Target(AnnotationTarget.FUNCTION) 8 | annotation class MethodOnly -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/custom/Normal.kt: -------------------------------------------------------------------------------- 1 | package annotation.custom 2 | 3 | annotation class Normal() 4 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/custom/Parameter.kt: -------------------------------------------------------------------------------- 1 | package annotation.custom 2 | 3 | @Target(AnnotationTarget.VALUE_PARAMETER) 4 | annotation class Parameter() 5 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/custom/PropertyGetterOnly.kt: -------------------------------------------------------------------------------- 1 | package annotation.custom 2 | 3 | 4 | @Target(AnnotationTarget.PROPERTY_GETTER) 5 | annotation class PropertyGetterOnly -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/custom/PropertyOnly.kt: -------------------------------------------------------------------------------- 1 | package annotation.custom 2 | 3 | /** 4 | * Desc: 5 | * Created by Chiclaim on 2018/10/15. 6 | */ 7 | @Target(AnnotationTarget.PROPERTY) 8 | annotation class PropertyOnly -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/custom/Tag.kt: -------------------------------------------------------------------------------- 1 | package annotation.custom 2 | 3 | // containing annotation 默认名字为 Tag$Container 4 | @Repeatable 5 | annotation class Tag() 6 | 7 | 8 | //@JvmRepeatable 自定义 containing annotation 的名字 9 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/java_repeatable/Main.java: -------------------------------------------------------------------------------- 1 | package annotation.java_repeatable; 2 | 3 | import annotation.custom.Tag; 4 | 5 | import java.lang.annotation.Annotation; 6 | import java.lang.reflect.Method; 7 | 8 | /** 9 | * @author kumushuoshuo 10 | * @github https://github.com/chiclaim/ 11 | */ 12 | public class Main { 13 | @Schedule(dayOfMonth = "last") 14 | @Schedule(dayOfWeek = "Fri", hour = 23) 15 | public void doPeriodicCleanup() { 16 | } 17 | 18 | // use kotlin repeatable annotation 19 | @Tag 20 | @Tag 21 | public void doJavaRepeatable() { 22 | } 23 | 24 | // 反射获取 repeatable 注解 25 | public static void main(String[] args) throws NoSuchMethodException { 26 | Method method = Main.class.getDeclaredMethod("doPeriodicCleanup"); 27 | Annotation[] annotations = method.getAnnotationsByType(Schedule.class); 28 | 29 | System.out.println("注解:"+annotations.length); 30 | for (Annotation annotation : annotations) { 31 | System.out.println(annotation); 32 | } 33 | 34 | method = Main.class.getDeclaredMethod("doJavaRepeatable"); 35 | annotations = method.getAnnotationsByType(Tag.class); 36 | System.out.println("注解:"+annotations.length); 37 | for (Annotation annotation : annotations) { 38 | System.out.println(annotation); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/java_repeatable/Schedule.java: -------------------------------------------------------------------------------- 1 | package annotation.java_repeatable; 2 | 3 | import java.lang.annotation.Repeatable; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | 7 | @Repeatable(Schedules.class) 8 | @Retention(RetentionPolicy.RUNTIME) 9 | public @interface Schedule { 10 | String dayOfMonth() default "first"; 11 | String dayOfWeek() default "Mon"; 12 | int hour() default 12; 13 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/java_repeatable/Schedules.java: -------------------------------------------------------------------------------- 1 | package annotation.java_repeatable; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | @Retention(RetentionPolicy.RUNTIME) 7 | public @interface Schedules { 8 | Schedule[] value(); 9 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/kotlin_annoation/DeprecatedTest.kt: -------------------------------------------------------------------------------- 1 | package annotation.kotlin_annoation 2 | 3 | class DeprecatedTest{ 4 | @Deprecated("use greeting", ReplaceWith("greeting()", 5 | "annotation.kotlin_annoation.DeprecatedTest.greeting()")) 6 | fun sayHello(){ 7 | println("hello...") 8 | } 9 | 10 | fun greeting(){ 11 | println("hello...") 12 | } 13 | } 14 | 15 | fun main() { 16 | val d = DeprecatedTest() 17 | d.sayHello() 18 | } 19 | 20 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/kotlin_annoation/JvmFieldTest.kt: -------------------------------------------------------------------------------- 1 | package annotation.kotlin_annoation 2 | 3 | class Person( 4 | @JvmField 5 | var name: String, 6 | var age: Int 7 | ) 8 | /* 9 | 10 | name 属性没有生成 getter、setter方法 11 | 并且该属性是public的,可以通过private显式指定为private 12 | 13 | 14 | public final class Person { 15 | @JvmField 16 | @NotNull 17 | public String name; 18 | private int age; 19 | 20 | public final int getAge() { 21 | return this.age; 22 | } 23 | 24 | public final void setAge(int var1) { 25 | this.age = var1; 26 | } 27 | 28 | public Person(@NotNull String name, int age) { 29 | Intrinsics.checkParameterIsNotNull(name, "name"); 30 | super(); 31 | this.name = name; 32 | this.age = age; 33 | } 34 | } 35 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/kotlin_annoation/JvmNameTest.java: -------------------------------------------------------------------------------- 1 | package annotation.kotlin_annoation; 2 | 3 | public class JvmNameTest { 4 | 5 | void test() { 6 | //invoke in java 7 | JavaClassName.java_method_name(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/kotlin_annoation/JvmNameTest.kt: -------------------------------------------------------------------------------- 1 | 2 | @file:JvmName("JavaClassName") 3 | 4 | package annotation.kotlin_annoation 5 | 6 | 7 | @JvmName("java_method_name") 8 | fun javaMethodName(){ 9 | println("java method name") 10 | } 11 | 12 | 13 | fun main() { 14 | //kotlin invoke 15 | javaMethodName() 16 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/kotlin_annoation/JvmStaticTest.kt: -------------------------------------------------------------------------------- 1 | package annotation.kotlin_annoation 2 | 3 | class JvmStaticTest { 4 | 5 | companion object { 6 | fun greeting() { 7 | println("hello...") 8 | } 9 | 10 | @JvmStatic 11 | fun sayHello() { 12 | println("hello...") 13 | } 14 | 15 | } 16 | 17 | } 18 | 19 | fun main() { 20 | JvmStaticTest.greeting() 21 | JvmStaticTest.sayHello() 22 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/kotlin_annoation/JvmStaticTestInJava.java: -------------------------------------------------------------------------------- 1 | package annotation.kotlin_annoation; 2 | 3 | public class JvmStaticTestInJava { 4 | 5 | void test(){ 6 | JvmStaticTest.Companion.greeting(); 7 | JvmStaticTest.sayHello(); 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/annotation/kotlin_annoation/SuppressTest.kt: -------------------------------------------------------------------------------- 1 | package annotation.kotlin_annoation 2 | 3 | @Suppress("UNCHECKED_CAST") 4 | fun test(source: Any) { 5 | if (source is List<*>) { 6 | val list = source as List 7 | val str: String = list[0] 8 | println(str) 9 | } 10 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/AlsoTest.kt: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | /** 4 | * Desc: also函数使用演示 5 | * Created by Chiclaim on 2018/10/17. 6 | */ 7 | 8 | fun main(args: Array) { 9 | //public inline fun T.also(block: (T) -> Unit): T 10 | val result = "chiclaim".also { 11 | println(it) 12 | } 13 | println(result) 14 | } 15 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/AnonymousFunctions.kt: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | fun main(args: Array) { 4 | 5 | (fun(x: Int, y: Int): Int { 6 | val result = x + y 7 | println("sum:$result") 8 | return result 9 | })(1, 9) 10 | 11 | 12 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/CompareTest.java: -------------------------------------------------------------------------------- 1 | package base; 2 | // 如果是 Java 则会抛出空指针异常,但是 Kotlin 不会 3 | 4 | // 看下 他们的 字节码区别: 5 | 6 | /* 7 | Kotlin---- 8 | public final static main()V 9 | L0 10 | LINENUMBER 25 L0 11 | GETSTATIC base/CompareTestKt.num : Ljava/lang/Integer; 12 | BIPUSH 42 13 | INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer; 14 | IF_ACMPNE L1 15 | L2 16 | LINENUMBER 26 L2 17 | LDC "success" 18 | ASTORE 0 19 | 20 | 21 | Java----- 22 | 23 | public static void main(java.lang.String[]); 24 | Code: 25 | 0: getstatic #2 // Field i:Ljava/lang/Integer; 26 | 3: invokevirtual #3 // Method java/lang/Integer.intValue:()I 27 | 6: bipush 42 28 | 8: if_icmpne 19 29 | 11: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 30 | 14: ldc #5 // String success 31 | 16: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 32 | 19: return 33 | 34 | 35 | 36 | Kotlin 和 Java 的比较机制不一样: 37 | 38 | Kotlin 是比较两个对象 39 | Java 是比较两个Integer的intValue 40 | 41 | 42 | */ 43 | public class CompareTest { 44 | 45 | private static Integer i; 46 | 47 | public static void main(String[] args) { 48 | if (i == 42) { 49 | System.out.println("success"); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/CompareTest.kt: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | 4 | 5 | // 如果是 Java 则会抛出空指针异常,但是 Kotlin 不会 6 | 7 | // 看下 他们的 字节码区别: 8 | 9 | /* 10 | Kotlin---- 11 | public final static main()V 12 | L0 13 | LINENUMBER 25 L0 14 | GETSTATIC base/CompareTestKt.num : Ljava/lang/Integer; 15 | BIPUSH 42 16 | INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer; 17 | IF_ACMPNE L1 18 | L2 19 | LINENUMBER 26 L2 20 | LDC "success" 21 | ASTORE 0 22 | 23 | 24 | Java----- 25 | 26 | public static void main(java.lang.String[]); 27 | Code: 28 | 0: getstatic #2 // Field i:Ljava/lang/Integer; 29 | 3: invokevirtual #3 // Method java/lang/Integer.intValue:()I 30 | 6: bipush 42 31 | 8: if_icmpne 19 32 | 11: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream; 33 | 14: ldc #5 // String success 34 | 16: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 35 | 19: return 36 | 37 | 38 | 39 | Kotlin 和 Java 的比较机制不一样: 40 | 41 | Kotlin 是比较两个对象 42 | Java 是比较两个Integer的intValue 43 | 44 | 45 | */ 46 | 47 | 48 | 49 | internal var num: Int? = null 50 | fun main() { 51 | 52 | if (num === 42) { 53 | println("success") 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/ExceptionTest.java: -------------------------------------------------------------------------------- 1 | package base; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | 6 | public class ExceptionTest { 7 | 8 | 9 | int readNumber( BufferedReader reader) throws IOException { 10 | try { 11 | String line = reader.readLine(); // throws IOException 12 | return Integer.parseInt(line); // throws NumberFormatException 13 | } catch (NumberFormatException e) { 14 | return -1; 15 | } finally { 16 | reader.close(); // throws IOException 17 | } 18 | 19 | } 20 | 21 | int readNumber2( BufferedReader reader) throws IOException { 22 | String line = reader.readLine(); // throws IOException 23 | //NumberFormatException 不是 checked exception 所以可以不处理,编译并不会报错 24 | return Integer.parseInt(line); 25 | } 26 | 27 | /*int readNumber3( BufferedReader reader) throws IOException { 28 | try (reader) { 29 | String line = reader.readLine(); // throws IOException 30 | return Integer.parseInt(line); // throws NumberFormatException 31 | } catch (NumberFormatException e) { 32 | return -1; 33 | } 34 | // throws IOException 35 | 36 | } 37 | */ 38 | 39 | 40 | public static void main(String[] args){ 41 | ExceptionTestKt.readNumber(null); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/ExceptionTest.kt: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | import java.io.BufferedReader 4 | import java.io.FileReader 5 | 6 | fun readNumber(reader: BufferedReader): Int? { 7 | try { 8 | val line = reader.readLine() //throws IOException 9 | return Integer.parseInt(line) 10 | } catch (e: NumberFormatException) { 11 | return null 12 | } finally { 13 | reader.close() //throws IOException 14 | } 15 | } 16 | 17 | fun readNumber2(reader: BufferedReader): Int? { 18 | reader.use { 19 | val line = reader.readLine() 20 | try { 21 | return Integer.parseInt(line) 22 | } catch (e: NumberFormatException) { 23 | return null 24 | } 25 | // 省略 reader.close() 26 | } 27 | } 28 | 29 | 30 | fun checkNumber(number: Int) { 31 | val percentage = if (number in 0..100) 32 | number 33 | else 34 | throw IllegalArgumentException( 35 | "A percentage value must be between 0 and 100: $number") 36 | } 37 | 38 | fun readFirstLineFromFile(path: String): String { 39 | BufferedReader(FileReader(path)).use { br -> 40 | return br.readLine() 41 | } 42 | } 43 | 44 | fun main() { 45 | 46 | println(checkNumber(1000)) 47 | 48 | readNumber(BufferedReader(FileReader("xx.txt"))) 49 | 50 | println("this is after readNumber") 51 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/ExtensionFuncTest.kt: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | // String 表示 receiver type 4 | // this 表示 receiver object 5 | fun String.lastChar(): Char = this.get(this.length - 1) 6 | 7 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/ExtensionProperty.kt: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | val String.lastChar: Char 4 | get() = this.get(length - 1) -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/FunctionVarargs.java: -------------------------------------------------------------------------------- 1 | package base; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | //int[] 当做 泛型 7 | class A extends FunctionVarargs{ 8 | 9 | } 10 | 11 | public class FunctionVarargs { 12 | 13 | private static void println(Object data) { 14 | System.out.println(data); 15 | } 16 | 17 | 18 | public static List listOf(T... items) { 19 | System.out.println(items.getClass()); 20 | return Arrays.asList(items); 21 | } 22 | 23 | public static void testArrays() { 24 | int[] intArr = {1, 2, 3}; 25 | List list = Arrays.asList(intArr); 26 | println(list.size()); 27 | } 28 | 29 | public static void testArrays2() { 30 | Integer[] intArr = {1, 2, 3}; 31 | List list = Arrays.asList(intArr); 32 | println(list.size()); 33 | } 34 | 35 | public static void testGeneric(T[] data) { 36 | int[][] intArray = {{1},{2}}; 37 | //T[] t = intArray; 非法 38 | } 39 | 40 | 41 | public static void main(String[] args) { 42 | 43 | //listOf(1, 2, 3, 4, 5); 44 | testArrays(); 45 | testArrays2(); 46 | 47 | int[] intArr = {1, 2}; 48 | 49 | //把 二维数组 传递 给 参数 是 一维泛型数组 的函数 50 | int[][] intArray = {{1},{2}}; 51 | // T[] ts = intArray 52 | testGeneric(intArray); // T[] 53 | 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/FunctionVarargs.kt: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | import java.util.* 4 | 5 | /*fun listOf(vararg items: T): List { 6 | return Arrays.asList(*items) // * spread operator 7 | }*/ 8 | 9 | fun main(args: Array) { 10 | //listOf(1, 2, 3, 4, 5) 11 | 12 | val intArr: Array = arrayOf(1, 2, 3, 4) 13 | 14 | Arrays.asList(0, *intArr).run { 15 | println("size = $size") 16 | } 17 | 18 | Arrays.asList(0, intArr).run { 19 | println("size = $size") 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/InFixFunction.kt: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | val map = mapOf(1 to "one", 7 to "seven", 53 to "fifty-three") 4 | 5 | val range = 0 until 10 6 | 7 | fun test(){ 8 | for (i in 100 downTo 0 step 2) { 9 | print("$i,") 10 | } 11 | 12 | println("------") 13 | 14 | for(i in 0 until 100){ 15 | print("$i-") 16 | } 17 | 18 | } 19 | 20 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/LambdaReturnValue.kt: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | fun main(args: Array) { 4 | 5 | listOf().filter { 6 | if (it in 1..9) { 7 | return@filter true //显式return 8 | } 9 | if (it in 10..19) { 10 | return@filter false //显式return 11 | } 12 | if (it in 20..29) { 13 | return@filter true //显式return 14 | } 15 | false //隐式return 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/LetTest.kt: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | /** 4 | * Desc: let常用于if判断 5 | * Created by Chiclaim on 2018/9/18. 6 | */ 7 | fun main(args: Array) { 8 | 9 | val email = getEmail() 10 | email?.let { it -> 11 | System.out.println(it) 12 | } 13 | 14 | } 15 | 16 | fun getEmail(): String? { 17 | return null 18 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/LoopTest.kt: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | 4 | fun main() { 5 | 6 | for (i in 0..100) { 7 | print("$i-") 8 | } 9 | 10 | println("------") 11 | 12 | for (i in 100 downTo 0 step 2) { 13 | print("$i,") 14 | } 15 | 16 | println("------") 17 | 18 | for(i in 0 until 100){ 19 | print("$i-") 20 | } 21 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/NothingTest.kt: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | fun main() { 4 | val address: String? = null 5 | val result = address ?: fail("No address") 6 | println(result.length) 7 | 8 | val address2: String? = "" 9 | val result2 = address2 ?: fail2("No address") 10 | //println(result2.length) 11 | } 12 | 13 | 14 | fun fail(message: String):Nothing { 15 | throw IllegalStateException(message) 16 | } 17 | fun fail2(message: String) { 18 | throw IllegalStateException(message) 19 | } 20 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/OperatorTest.kt: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | /** 4 | * desc: Kotlin 操作符 演示 5 | * 6 | * ==、===、is、as 7 | * 8 | * Created by Chiclaim on 2018/09/19 9 | */ 10 | 11 | class Person(var name: String) 12 | 13 | fun getPerson(): Person? = null 14 | 15 | // == 操作符 相当于Java里的equals()方法 16 | // === 操作符 相当于Java里的 == 17 | fun equalsTest() { 18 | val p1 = Person("chiclaim") 19 | val p2 = getPerson() 20 | println(p2 == p1) 21 | 22 | /* 23 | == 底层调用 Intrinsics.areEqual(p2, p1); 方法 24 | 虽然 kotlin == 相当于 java equals,kotlin避免了空指针异常 25 | 26 | //这样的判断逻辑非常精妙 27 | public static boolean areEqual(Object first, Object second) { 28 | return first == null ? second == null : first.equals(second); 29 | } 30 | */ 31 | 32 | println(p2 === p1) 33 | 34 | /* 35 | === 编译后代码如下: 36 | 37 | var2 = p2 == p1; 38 | System.out.println(var2); 39 | */ 40 | } 41 | 42 | // is 操作符 相当于Java里的 instanceof 43 | fun isTest(other: Any?) { 44 | if (other is Person) { // !is 45 | println("${other.name} is a person") 46 | } 47 | /* 48 | public static final void isTest(@Nullable Object other) { 49 | if (other instanceof Person) { 50 | String var1 = ((Person)other).getName() + " is a person"; 51 | System.out.println(var1); 52 | } 53 | } 54 | 55 | */ 56 | } 57 | 58 | // as as? 操作符 59 | fun asTest(other: Any?) { 60 | val p = other as Person 61 | /* 62 | val p = other as Person编译后对应的Java代码: 63 | if (other == null) { 64 | throw new TypeCastException("null cannot be cast to non-null type base.Person"); 65 | } else { 66 | Person p = (Person)other; 67 | } 68 | 据此可以得出 as 操作符可能抛出两种异常: 69 | 1, java.lang.ClassCastException 70 | 2, kotlin.TypeCastException 71 | 72 | 但是如果是在Java中,把null进行强制类型转换并不会抛出异常: 73 | Object other = null; 74 | System.out.println((String)other); 75 | */ 76 | 77 | 78 | //val p1 = other as? Person 79 | /* 80 | as? 不管other是null,还是other是不是Person类型,都不会抛出异常,如果不能强转则最终的结果为null 81 | 82 | 编译class字节码后对应的Java代码如下: 83 | Object var10000 = other; 84 | if (!(other instanceof Person)) { 85 | var10000 = null; 86 | } 87 | 88 | Person p1 = (Person)var10000; 89 | */ 90 | } 91 | 92 | fun main(args: Array) { 93 | isTest("") 94 | isTest(null) 95 | isTest(Person("chiclaim")) 96 | 97 | //asTest(null) //throw kotlin.TypeCastException 98 | asTest("") 99 | } 100 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/RunTest.kt: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | /** 4 | * Desc: run函数使用,和LambdaWithReceiver.kt进行对比 5 | * Created by Chiclaim on 2018/10/17. 6 | */ 7 | 8 | //inline fun run(block: () -> R): R 9 | fun runTest() = run { 10 | println("====") 11 | "this is run return" 12 | } 13 | 14 | 15 | //lambda参数是this的,this就是lambda receiver 16 | //lambda receiver 17 | //inline fun T.run(block: T.() -> R): R 18 | fun runTest2() = StringBuilder().run { 19 | for (c in 'A'..'Z') { 20 | append(c) 21 | } 22 | append("\nNow I know the alphabet!") 23 | } 24 | 25 | fun main(args: Array) { 26 | 27 | println(runTest()) 28 | println(runTest2()) 29 | 30 | } 31 | 32 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/SpreadOperatorTest.kt: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | import java.util.* 4 | 5 | fun main() { 6 | val intArr: Array = arrayOf(1, 2, 3, 4) 7 | Arrays.asList(intArr).run { 8 | println("size = ${this.size}") 9 | } 10 | /* 11 | 上面反编译出来的代码: 12 | 13 | Integer[] intArr = new Integer[]{1, 2, 3, 4}; 14 | List var1 = Arrays.asList(intArr); 15 | System.out.println(var1.size()); 16 | 17 | 这样的Java代码 运行结果是 size=4 18 | 19 | 20 | 但是上面的Kotlin代码运行结果是 size=1 ???? 21 | */ 22 | 23 | 24 | 25 | 26 | val intArr2: Array = arrayOf(1, 2, 3, 4) 27 | Arrays.asList(0, *intArr2).run { 28 | println("size = $size") 29 | } 30 | /* 31 | 反编译对应的Java代码: 32 | 33 | Integer[] intArr2 = new Integer[]{1, 2, 3, 4}; 34 | SpreadBuilder var10000 = new SpreadBuilder(2); 35 | var10000.add(0); //第1个元素 36 | var10000.addSpread(intArr2); //数组里的4个元素 37 | List var2 = Arrays.asList((Integer[])var10000.toArray(new Integer[var10000.size()])); 38 | int var7 = false; 39 | String var5 = "size = " + var2.size(); 40 | System.out.println(var5); 41 | */ 42 | 43 | 44 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/StringTest.java: -------------------------------------------------------------------------------- 1 | package base; 2 | 3 | public class StringTest { 4 | 5 | public static void main(String[] args) { 6 | String[] arr = "www.chiclaim.com".split("."); 7 | System.out.println(arr.length); // length = 0 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/StringTest.kt: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | fun main() { 4 | val arr = "www.chiclaim.com".split(".") 5 | println(arr.size) // size = 3 6 | val path = "/Users/chiclaim/kotlin-book/kotlin-in-action.doc" 7 | 8 | parsePathRegexp(path) 9 | parsePath(path) 10 | 11 | val kotlinLogo = """ 12 | | // 13 | .|// 14 | .|/ \""" 15 | 16 | println(kotlinLogo) 17 | } 18 | 19 | fun parsePathRegexp(path: String) { 20 | val regex = """(.+)/(.+)\.(.+)""".toRegex() 21 | val matchResult = regex.matchEntire(path) 22 | if (matchResult != null) { 23 | val (directory, filename, extension) = matchResult.destructured 24 | println("Dir: $directory, name: $filename, ext: $extension") 25 | } 26 | } 27 | 28 | fun parsePath(path: String) { 29 | val directory = path.substringBeforeLast("/") 30 | val fullName = path.substringAfterLast("/") 31 | val fileName = fullName.substringBeforeLast(".") 32 | val extension = fullName.substringAfterLast(".") 33 | println("Dir: $directory, name: $fileName, ext: $extension") 34 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/TopLevelTest.kt: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | var topLevelProperty:Int = 0 4 | 5 | fun topLevelFun(){ 6 | 7 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/base/WhenTest.kt: -------------------------------------------------------------------------------- 1 | package base 2 | 3 | import new_class.Color 4 | import new_class.Color.* 5 | 6 | 7 | // when with enum 8 | fun getMnemonic(color: Color) = when (color) { 9 | Color.RED -> "Richard" 10 | Color.ORANGE -> "Of" 11 | Color.YELLOW -> "York" 12 | Color.GREEN -> "Gave" 13 | Color.BLUE -> "Battle" 14 | Color.INDIGO -> "In" 15 | Color.VIOLET -> "Vain" 16 | } 17 | 18 | 19 | fun mix(c1: Color, c2: Color) = when (setOf(c1, c2)) { 20 | setOf(RED, YELLOW) -> ORANGE 21 | setOf(YELLOW, BLUE) -> GREEN 22 | setOf(BLUE, VIOLET) -> INDIGO 23 | else -> throw Exception("Dirty color") 24 | } 25 | 26 | 27 | fun mixOptimized(c1: Color, c2: Color) = when { 28 | (c1 == RED && c2 == YELLOW) || (c1 == YELLOW && c2 == RED) -> 29 | ORANGE 30 | (c1 == YELLOW && c2 == BLUE) || (c1 == BLUE && c2 == YELLOW) -> 31 | GREEN 32 | (c1 == BLUE && c2 == VIOLET) || (c1 == VIOLET && c2 == BLUE) -> 33 | INDIGO 34 | else -> throw Exception("Dirty color") 35 | } 36 | 37 | internal fun test(obj: Any) { 38 | when (obj) { 39 | is String -> obj.substring(0, obj.length / 2) 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/collection/AllAnyCountFindGroupByTest.kt: -------------------------------------------------------------------------------- 1 | package collection 2 | 3 | import lambda.Person 4 | import lambda.list 5 | 6 | /** 7 | * desc: all、any、count、find、firstOrNull、groupBy使用演示 8 | * 9 | * Created by Chiclaim on 2018/09/22 10 | */ 11 | 12 | 13 | fun main(args: Array) { 14 | val predicate = { p: Person -> 15 | p.age > 20 16 | } 17 | 18 | //是否所有人的年龄大于20 19 | list.all(predicate).apply { 20 | println(this) 21 | } 22 | 23 | //是否有一个年龄大于20的人 24 | list.any(predicate).apply { 25 | println(this) 26 | } 27 | 28 | //尽量少用 ! (下面两句是等价的,少用!,避免增加理解难度) 29 | println(!list.all { person -> person.age == 27 }) 30 | println(list.any { person -> person.age != 27 }) 31 | 32 | //年龄大于20的总人数 33 | list.count(predicate).apply { 34 | println(this) 35 | } 36 | 37 | //获取第一个年龄大于20的人 38 | //find 等价 firstOrNull() 39 | list.find(predicate).apply { 40 | println(this) 41 | } 42 | 43 | 44 | //按年龄分组 45 | list.groupBy(Person::age).apply { 46 | println(this) 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/collection/CollectionCreateTest.kt: -------------------------------------------------------------------------------- 1 | package collection 2 | 3 | /** 4 | * Desc: Kotlin中创建集合演示 5 | * Created by Chiclaim on 2018/9/28. 6 | */ 7 | 8 | //Kotlin中分为只读集合和可修改的集合 9 | 10 | 11 | fun readOnlyCollection() { 12 | val list = listOf("Java", "Kotlin", "Python") 13 | //listOf函数底层通过Java的Arrays$ArrayList来实现的 class java.util.Arrays$ArrayList 14 | //Arrays.asList(...) 15 | println(list.javaClass) 16 | println(list) 17 | 18 | val set = setOf("Sun", "Moon", "Earth") 19 | //class java.util.LinkedHashSet 20 | println(set.javaClass) 21 | println(set) 22 | set.size 23 | 24 | 25 | val map = mapOf("name" to "chiclaim", "gender" to "male", "address" to "hangzhou") 26 | //class java.util.LinkedHashMap 27 | println(map.javaClass) 28 | println(map) 29 | 30 | //在Kotlin中通过自定义了一套只读的集合接口:List、Set、Map,不会提供修改集合的方法 31 | //在编译后会转成Java的 List、Set、Map接口 32 | 33 | 34 | } 35 | 36 | fun modifyCollection() { 37 | //java.util.ArrayList 38 | val list = mutableListOf("chiclaim") 39 | list.add("johnny") 40 | println(list.javaClass) 41 | println(list) 42 | 43 | //java.util.LinkedHashSet 44 | val set = mutableSetOf("Java") 45 | set.add("Kotlin") 46 | println(set.javaClass) 47 | println(set) 48 | 49 | //java.util.LinkedHashMap 50 | val map = mutableMapOf("name" to "johnny") 51 | map["address"] = "hangzhou" 52 | println(map.javaClass) 53 | println(map) 54 | 55 | //对于可修改的结合,Kotlin定义一套接口:MutableList、MutableSet、MutableMap 56 | //在编译后会转成Java的 List、Set、Map接口 57 | 58 | 59 | //除了上面的 MutableXXX,还可以通过下面的方式来创建可修改结合,这个没用MutableXXX接口,直接使用Java的集合 60 | 61 | //java.util.ArrayList 62 | arrayListOf("chiclaim") 63 | 64 | //java.util.HashSet 65 | hashSetOf("chiclaim") 66 | //java.util.LinkedHashSet 67 | linkedSetOf("chiclaim") 68 | //java.util.TreeSet 69 | sortedSetOf("chiclaim") 70 | 71 | //java.util.HashMap 72 | hashMapOf("name" to "chiclaim") 73 | //java.util.LinkedHashMap 74 | linkedMapOf("name" to "chiclaim") 75 | //java.util.TreeHashMap 76 | sortedMapOf("name" to "chiclaim") 77 | 78 | } 79 | 80 | //Kotlin中只读集合被Java代码修改的问题 81 | fun processWithJava() { 82 | //自定义一个只读集合 83 | val list = listOf(1, 2, 3, 4, 5, 6) 84 | //把集合传递给Java方法,只读集合可能就被修改了 85 | ListJava.updateList(list) 86 | println(list) 87 | } 88 | 89 | 90 | fun main(args: Array) { 91 | readOnlyCollection() 92 | println() 93 | modifyCollection() 94 | println() 95 | processWithJava() 96 | } 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/collection/CollectionNullabilityTest.kt: -------------------------------------------------------------------------------- 1 | package collection 2 | 3 | /** 4 | * Desc: Kotlin集合 为空性演示 5 | * Created by Chiclaim on 2018/9/18. 6 | */ 7 | 8 | fun main(args: Array) { 9 | test2() 10 | } 11 | 12 | //演示 MutableList 和 MutableList? 的区别 13 | fun test() { 14 | val arr: MutableList = mutableListOf() 15 | var arr2: MutableList = mutableListOf() 16 | 17 | arr.add(null) //legal 18 | //arr = null //illegal 19 | 20 | //arr2.add(null) //illegal 21 | 22 | var arr3: MutableList? = mutableListOf() 23 | arr3 = null //legal 24 | 25 | 26 | } 27 | 28 | //演示 Kotlin使用Java集合数据,可能产生的问题 29 | fun test2() { 30 | //首先声明一个集合,且集合里的元素不能为空 31 | val arr1: MutableList = mutableListOf() 32 | //然后调用一个Java写的ListJava获取一个集合(集合元素可能为null),把该集合的里的元素一个个放进arr1 33 | ListJava.getList().forEach { value -> 34 | //编译时会在add插入前进行判断:Intrinsics.checkExpressionValueIsNotNull(value, "value"); 35 | arr1.add(value) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/collection/FilterMapTest.kt: -------------------------------------------------------------------------------- 1 | package collection 2 | 3 | import lambda.Person 4 | import lambda.list 5 | 6 | /** 7 | * desc: filter、map函数 使用演示和原理分析 8 | * 9 | * Created by Chiclaim on 2018/09/22 10 | */ 11 | 12 | 13 | //filter函数的底层也是通过新建一个集合,然后遍历数据源,把符合条件的元素放进新的集合中 14 | fun filterTest() { 15 | list.filter { person -> 16 | person.age > 18 17 | }.apply { 18 | println(this) 19 | } 20 | 21 | //找出年龄最大的人(可能存在多个) 22 | //我们在filter里面使用了maxBy函数,底层通过嵌套循环实现的,效率低(O(n^2))) 23 | list.filter { person -> 24 | person.age == list.maxByOrNull {it.age}?.age 25 | }.apply { 26 | println(this) 27 | } 28 | 29 | //上面问题的改良版,把嵌套循环扁平化(O(n)) 30 | val maxAge = list.maxByOrNull { it.age }?.age 31 | list.filter { person -> 32 | person.age == maxAge 33 | }.apply { 34 | println(this) 35 | } 36 | 37 | } 38 | 39 | //上面filter可以过滤元素,map可以修改集合的元素 40 | fun mapTest() { 41 | 42 | //收集用户的名字 43 | list.map { person -> 44 | person.name 45 | }.apply { 46 | println(this) 47 | } 48 | 49 | //通过member reference替代上面的实现方式,需要把大括号改成小括号 50 | list.map(Person::name).apply { 51 | println(this) 52 | } 53 | 54 | //为每个人加1岁. 需要注意的是此时并不会新建新集合,操作的是原来数据源的元素 55 | list.map { person -> 56 | person.age += 1 57 | } 58 | println(list)// print original list 59 | 60 | 61 | //filter、map组合使用 62 | //底层是通过两个循环实现的 63 | //第一个循环是filter出年龄大于20 64 | //第二个循环是遍历上面的新集合,取出他们的名字 65 | list.filter { person -> 66 | person.age > 20 67 | }.map(Person::name).apply { 68 | println("age > 20 : $this") 69 | } 70 | } 71 | 72 | fun main(args: Array) { 73 | filterTest() 74 | //mapTest() 75 | 76 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/collection/FlatMapFlattenTest.kt: -------------------------------------------------------------------------------- 1 | package collection 2 | 3 | import lambda.Person 4 | 5 | /** 6 | * desc: flatMap、flatten函数使用演示 7 | * 8 | * Created by Chiclaim on 2018/09/22 9 | */ 10 | 11 | fun main(args: Array) { 12 | 13 | val people = listOf(Person("Peter", 35).apply { 14 | val children = listOf(Person("Lily", 12), Person("Lucy", 8)) 15 | this.children = children 16 | }) 17 | 18 | people.map(Person::children).apply { 19 | println(this) //List> 20 | } 21 | 22 | //flatMap vs map 23 | 24 | //map函数把每个person的children集合放到新集合中,最终返回的记过是集合嵌套 25 | //flat是扁平的意思,flatMap把每个person的每个child放到集合 26 | people.flatMap { it.children }.apply { 27 | println(this) //List 28 | } 29 | 30 | 31 | //我们也可以把集合嵌套通过flatten函数将其扁平化 32 | //如上面的map函数返回的List扁平化成List 33 | people.map(Person::children).flatten().apply { 34 | println(this) //List 35 | } 36 | 37 | 38 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/collection/ImpJavaInterfaceWhenCollection.kt: -------------------------------------------------------------------------------- 1 | package collection 2 | 3 | import base.Person 4 | import java.io.File 5 | 6 | /** 7 | * Desc: 由于Java和Kotlin在集合的可修改的差异性,Kotlin在实现Java接口(接口方法有集合参数)时需要注意: 8 | * 1,集合是否可为null 9 | * 2,集合里的元素是否可为null 10 | * 3,集合是否可修改 11 | * 12 | * Created by Chiclaim on 2018/9/28. 13 | */ 14 | 15 | //下面是Kotlin实现Java接口关于Nullability上的处理 的例子(from kotlin in action) 16 | 17 | class FileIndexer : ListJava.FileContentProcessor { 18 | override fun processContents(path: File, 19 | binaryContents: ByteArray?, 20 | textContents: List?) { 21 | // ... 22 | println() 23 | } 24 | } 25 | 26 | 27 | class PersonParser : ListJava.DataParser { 28 | override fun parseData(input: String, 29 | output: MutableList, 30 | errors: MutableList) { 31 | // ... 32 | } 33 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/collection/LazyCollectionTest.kt: -------------------------------------------------------------------------------- 1 | package collection 2 | 3 | import lambda.Person 4 | import lambda.list 5 | 6 | /** 7 | * desc: lazy collection和非 lazy collection 对比演示 8 | * 9 | * Created by Chiclaim on 2018/09/23 10 | */ 11 | 12 | // 创建 sequence: 13 | // sequenceOf 14 | // asSequence 15 | // generateSequence 16 | 17 | fun main(args: Array) { 18 | 19 | // collectionTest() 20 | // lazyCollectionTest() 21 | // println("============================") 22 | lazyCollectionTest2() 23 | 24 | // lazyCollectionTest3() 25 | } 26 | 27 | fun collectionTest() { 28 | // 没经过一个操作符 都会创建一个临时的集合,用于保存中间结果 29 | list.map(Person::age).filter { age -> 30 | age > 18 31 | }.forEach { 32 | println(it) 33 | } 34 | 35 | /* 36 | 37 | 通过编译后对应的Java代码可以发现,经过map和filter函数,创建了两个临时集合: 38 | 39 | Iterable $receiver$iv = (Iterable)PersonKt.getList(); 40 | //创建集合 41 | Collection destination$iv$iv = (Collection)(new ArrayList(CollectionsKt.collectionSizeOrDefault($receiver$iv, 10))); 42 | Iterator var4 = $receiver$iv.iterator(); 43 | Object element$iv$iv; 44 | while(var4.hasNext()) { 45 | element$iv$iv = var4.next(); 46 | Integer var11 = ((Person)element$iv$iv).getAge(); 47 | destination$iv$iv.add(var11); 48 | } 49 | $receiver$iv = (Iterable)((List)destination$iv$iv); 50 | 51 | //创建集合 52 | destination$iv$iv = (Collection)(new ArrayList()); 53 | var4 = $receiver$iv.iterator(); 54 | 55 | while(var4.hasNext()) { 56 | element$iv$iv = var4.next(); 57 | int age = ((Number)element$iv$iv).intValue(); 58 | if (age > 18) { 59 | destination$iv$iv.add(element$iv$iv); 60 | } 61 | } 62 | */ 63 | } 64 | 65 | fun lazyCollectionTest() { 66 | list.asSequence().map { person -> 67 | println("map ${person.age}") 68 | person.age 69 | }.filter { age -> 70 | println("filter $age") 71 | age > 20 72 | }//.toList() 73 | //或者下面的遍历 74 | .forEach { 75 | println("---------forEach $it") 76 | } 77 | 78 | } 79 | 80 | fun lazyCollectionTest2() { 81 | //把filter函数放置前面,可以有效减少map函数的调用次数 82 | list.asSequence().filter { person -> 83 | println("filter ${person.age}") 84 | person.age > 20 85 | }.map { person -> 86 | println("map ${person.age}") 87 | person.age 88 | }.forEach { 89 | println("---------forEach $it") 90 | } 91 | 92 | } 93 | 94 | //create sequence 95 | fun lazyCollectionTest3() { 96 | generateSequence(0) { 97 | it + 1 98 | }.takeWhile { 99 | it <= 100 100 | }.sum().apply { 101 | println(this) 102 | } 103 | } 104 | 105 | /* 106 | 经过分析class字节码、对应的Java代码以及debug跟踪调试,lazy collection 有如下优点: 107 | 108 | 1,不会创建临时集合 109 | 2,用到集合元素的时候,如遍历或转化成新集合(forEach,toList),才会触发集合的过滤、转化等操作。(某种意义上讲和RxJava有点类似) 110 | 111 | 112 | */ 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/collection/ListJava.java: -------------------------------------------------------------------------------- 1 | package collection; 2 | 3 | import java.io.File; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | /** 7 | * Desc: 8 | * Created by Chiclaim on 2018/9/18. 9 | */ 10 | public class ListJava { 11 | public static List getList() { 12 | return Arrays.asList(null, 1, 2, 3); 13 | } 14 | 15 | 16 | public static void updateList(List list) { 17 | for (int i = 0; i < list.size(); i++) { 18 | list.set(i, list.get(i) + 100); 19 | } 20 | } 21 | 22 | public interface DataParser { 23 | void parseData(String input, List output, List errors); 24 | } 25 | 26 | 27 | interface FileContentProcessor { 28 | void processContents(File path, byte[] binaryContent, List textContents); 29 | } 30 | } 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/data_type/NothingTypeTest.kt: -------------------------------------------------------------------------------- 1 | package data_type 2 | 3 | /** 4 | * Desc: Nothing 类型详解 5 | * Created by Chiclaim on 2018/9/27. 6 | */ 7 | 8 | class Person(var name: String?) 9 | 10 | 11 | fun test() { 12 | val p = Person(null) 13 | val name = p.name ?: throw IllegalArgumentException("name is null") 14 | println(name.length) 15 | } 16 | 17 | fun fail(message: String) { 18 | throw IllegalArgumentException(message) 19 | } 20 | 21 | fun test2() { 22 | val p = Person(null) 23 | //为什么下面的表达式成立呢?虽然fail的没有写返回值,但是它的默认返回值Unit,所以表达式成立 24 | val name = p.name ?: fail("name is null") 25 | //编译器报错 26 | //println(name.length) 27 | } 28 | 29 | //fail方法和fail2方法类似,只不过fail2返回Nothing类型 30 | fun fail2(message: String): Nothing { 31 | throw IllegalArgumentException(message) 32 | } 33 | 34 | 35 | fun test3() { 36 | val p = Person(null) 37 | //Nothing一般用于 Elvis 操作符 38 | val name:String = p.name ?: fail2("name is null") 39 | //编译器发现fail2返回Nothing,那么这个方法肯定不会正常退出的, 如果异常退出,name就不能顺利的赋值,所以编译认为name肯定是一个非空类型 40 | println(name.length) 41 | } 42 | 43 | // Nothing is subtype of all types 44 | fun test4() { 45 | var value: String = fail2("err") 46 | } 47 | 48 | fun test5(){ 49 | val nothing:Nothing = Nothing::class.java.newInstance() 50 | } 51 | 52 | 53 | fun main(args: Array) { 54 | 55 | fail2("err") 56 | 57 | // test() 58 | // 59 | // test2() 60 | // 61 | // test3() 62 | // 63 | TODO() 64 | 65 | } 66 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/data_type/NumberConversion.kt: -------------------------------------------------------------------------------- 1 | package data_type 2 | 3 | /** 4 | * Desc: Java会自动类型转换,Kotlin大部分需要显式类型转换 5 | * Created by Chiclaim on 2018/9/27. 6 | */ 7 | 8 | 9 | fun main(args: Array) { 10 | val age = 30 11 | //val longAge: Long = age 12 | //需要显式进行类型转换 13 | val longAge: Long = age.toLong() 14 | 15 | //TODO 为什么类型转换函数没有方法体 16 | 17 | 18 | val longMoney: Long = 45000000 19 | //大范围类型转小范围类型 20 | val intMoney = longMoney.toInt() 21 | 22 | 23 | val x = 10 24 | //集合元素会自动转成最大数据类型:Long 25 | val list = listOf(10, 20, 30L) 26 | for (v in list) { 27 | println("${v.javaClass} $v") 28 | //Operator '==' cannot be applied to 'Int' and 'Long' 29 | //if (x == v) { } 30 | } 31 | 32 | //类型不兼容 33 | //println(x in list ) 34 | println(x.toLong() in list) 35 | 36 | 37 | val y: Byte = 1 38 | //y 向上转成 Long 39 | val z = y + 1L 40 | println(z) 41 | 42 | val intValue = 10 43 | //传递参数的时Int变量不能当做参数传递给需要Long参数的方法 44 | //printLong(intValue) 45 | //字面量Int可以传递给需要Long参数的方法(自动类型转换) 46 | printLong(10) 47 | 48 | } 49 | 50 | fun printLong(value: Long) { 51 | println(value) 52 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/data_type/NumberTypeTest.kt: -------------------------------------------------------------------------------- 1 | package data_type 2 | 3 | /** 4 | * Desc: 在Java中数据类型有基本数据类型和与其对应的包装类型 5 | * 6 | * 在Kotlin不用区分基本类型和包装类型,Kotlin重新定义了数据类型的关键字如:Char、Float、Int 等 7 | * 8 | * 但是在编译后也会把能编译成基本类型编译成基本类型 9 | * 10 | * 下面会列举出各种使用数据类型的情况,及其编译后对应是基本了类型还是包装类型 11 | * 12 | * 编译后是基本类型还是包装类型总结: 13 | * 14 | * 1,如果使用了泛型则编译后是包装类型,如集合泛型、数组泛型 15 | * 2,如果想要声明的数组编译是基本类型的数组,需要使用xxxArrayOf(...),如intArrayOf 16 | * 2,如果变量可以为null(使用操作符`?`),则编译后也是包装类型 17 | * 18 | * Created by Chiclaim on 2018/9/18. 19 | */ 20 | 21 | 22 | //为什么Kotlin不用Java里的基本数据类型,因为基本数据类型就无法调用一些有用的方法了 23 | //下面使用Int就可以使用它的一些扩展方法,在编译后依然会编译成基本数据类型int 24 | fun showProgress(progress: Int) { 25 | val percent = progress.coerceIn(0, 100) 26 | println("We're $percent% done!") 27 | } 28 | 29 | 30 | //会编译成基本类型int,同时会生成getter和setter方法 31 | var width1: Int = 10 32 | 33 | //会编译成Integer,同时会生成getter和setter方法 34 | //因为可以为null,所以编译后不能是int基本类型 35 | var width2: Int? = 10 36 | 37 | //也会编译成Integer 38 | val width3: Int? = 10 39 | 40 | //会编译成一个Integer类型 41 | var width4: Int? = null 42 | 43 | //private static Object autoBox = Integer.valueOf(1); 44 | var autoBox: Any = 1 45 | 46 | //返回值Int编译后变成基本类型int 47 | fun getAge(): Int { 48 | return 0 49 | } 50 | 51 | //返回值Int编译后变成Integer 52 | fun getAge2(): Int? { 53 | return 0 54 | } 55 | 56 | //集合里的元素都是Integer类型 57 | fun getAge3(): List { 58 | return listOf(22, 90, 50) 59 | } 60 | 61 | //会编译成一个Integer[] 62 | fun getAge4(): Array { 63 | return arrayOf(170, 180, 190) 64 | } 65 | 66 | //会编译成一个int[] 67 | fun getAge5(): IntArray { 68 | return intArrayOf(170, 180, 190) 69 | } 70 | 71 | fun main(args: Array) { 72 | showProgress(111) 73 | 74 | //println(getAge() > getAge2()) 75 | //println(getAge() > getAge2() ?: 0) 76 | } 77 | 78 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/data_type/UnitTypeTest.kt: -------------------------------------------------------------------------------- 1 | package data_type 2 | 3 | /** 4 | * Desc: Unit和Void 5 | * Created by Chiclaim on 2018/9/27. 6 | */ 7 | 8 | //Kotlin中的Unit和Java的Void一样,一般用于方法没有返回值 9 | 10 | //和Java不同的是,如果不需要返回值,Kotlin方法可以省略Unit关键字 11 | 12 | fun foo(): Unit { 13 | 14 | } 15 | 16 | fun foo2() { //省略 Unit 17 | 18 | } 19 | 20 | //Unit用于类泛型的时候,如果Unit作为该类方法返回值的话,则表示该方法没有返回值,不会像Java一样一定要返回一个Void类型 21 | //Kotlin不需要这样做是因为Kotlin已经在编译的时候已经替我们返回了一个Unit,底层是通过一个桥接方法来实现的,具体可以查看class字节码 22 | //需要注意到是,一个普通返回Unit的方法,不会有额外的桥接方法,只有泛型作为方法返回值是才会,如下面的例子 23 | 24 | interface Processor { 25 | //子类实现该方法,都会在子类中产生一个额外process桥接方法 26 | fun process(): T 27 | } 28 | 29 | 30 | class NoResultProcessor : Processor { 31 | //会有桥接方法 32 | override fun process() { 33 | println("process") 34 | } 35 | 36 | //不会产生桥接方法 37 | fun genericMethod(t: T): T { 38 | return t 39 | } 40 | } 41 | 42 | class StringProcessor : Processor { 43 | //会有桥接方法 44 | override fun process(): String { 45 | return "this is a String" 46 | } 47 | 48 | } 49 | 50 | fun main(args: Array) { 51 | //对于Kotlin来说任何方法都有返回值的,如果没有指定返回值,那么这个方法的返回值类型就是Unit 52 | println(foo2().javaClass) 53 | } 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/data_type/VoidTypeTest.java: -------------------------------------------------------------------------------- 1 | package data_type; 2 | 3 | /** 4 | * Desc: 5 | * Created by Chiclaim on 2018/9/27. 6 | */ 7 | 8 | //Java Void 和 Kotlin Unit 的对比 9 | 10 | interface MyProcessor { 11 | T process(); 12 | } 13 | 14 | public class VoidTypeTest implements MyProcessor { 15 | @Override 16 | public Void process() { 17 | return null; 18 | } 19 | } 20 | 21 | class MyStringProcessor implements MyProcessor { 22 | @Override 23 | public String process() { 24 | return "This is a String"; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/delegated/DelegatedPropertyBy.kt: -------------------------------------------------------------------------------- 1 | package delegated 2 | 3 | import kotlin.reflect.KProperty 4 | 5 | /** 6 | * 7 | * @author kumushuoshuo 8 | * @github https://github.com/chiclaim/ 9 | */ 10 | class Delegate { 11 | operator fun getValue(thisRef: Any?, property: KProperty<*>): String { 12 | return "$thisRef, thank you for delegating '${property.name}' to me!" 13 | } 14 | 15 | operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { 16 | println("$value has been assigned to '${property.name}' in $thisRef.") 17 | } 18 | } 19 | 20 | class Example { 21 | var p: String by Delegate() 22 | 23 | // setter -> setValue 24 | // getter -> getValue 25 | } 26 | 27 | fun main() { 28 | 29 | val e = Example() 30 | e.p = "kumushuoshuo" 31 | println(e.p) 32 | } 33 | 34 | class P { 35 | var name:String = "kumushuoshsuo" 36 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/delegated/DelegatedPropertyByLazy.kt: -------------------------------------------------------------------------------- 1 | package delegated 2 | 3 | /** 4 | * Desc: delegated property 5 | * Created by Chiclaim on 2018/9/30. 6 | */ 7 | /* 8 | //代理属性实现原理 9 | class Foo { 10 | private val delegate = Delegate() 11 | var p: Type 12 | set(value: Type) = delegate.setValue(..., value) 13 | get() = delegate.getValue(...) 14 | } 15 | 16 | class Delegate { 17 | operator fun getValue(...) { ... } 18 | operator fun setValue(..., value: Type) { ... } 19 | } 20 | */ 21 | 22 | //Kotlin lazy函数就是使用了delegated property,实现原理大致如下(非线程安全): 23 | class Person(val name: String) { 24 | //存储值,不对外暴露, 25 | private var _emails: List? = null 26 | //对外暴露,延迟加载 27 | val emails: List 28 | get() { 29 | if (_emails == null) { 30 | _emails = loadEmail() 31 | } 32 | return _emails!! 33 | } 34 | 35 | private fun loadEmail() = listOf("chiclaim@gmail.com", "chiclaim@163.com") 36 | 37 | } 38 | 39 | //Kotlin lazy 的使用 40 | class Person2(val name: String) { 41 | val emails:List by lazy { 42 | loadEmail() 43 | } 44 | 45 | private fun loadEmail() = listOf("chiclaim@gmail.com", "chiclaim@163.com") 46 | 47 | } 48 | 49 | //Kotlin lazy 的使用 50 | class DelegatedProperty { 51 | val friends by lazy { 52 | loadFriendList() 53 | } 54 | 55 | private fun loadFriendList(): List { 56 | return listOf("pony", "johnny", "jack") 57 | } 58 | } 59 | 60 | /* 61 | 62 | Kotlin lazy 源码分析 63 | 64 | private class SynchronizedLazyImpl(initializer: () -> T, lock: Any? = null) : Lazy, Serializable { 65 | private var initializer: (() -> T)? = initializer 66 | //用于存储值。初始值为UNINITIALIZED_VALUE 67 | @Volatile private var _value: Any? = UNINITIALIZED_VALUE 68 | // final field is required to enable safe publication of constructed instance 69 | private val lock = lock ?: this 70 | 71 | override val value: T 72 | get() { 73 | val _v1 = _value 74 | //如果不是初始值说明已经赋过值了,直接返回 75 | if (_v1 !== UNINITIALIZED_VALUE) { 76 | @Suppress("UNCHECKED_CAST") 77 | return _v1 as T 78 | } 79 | //下面进入同步代码块 80 | return synchronized(lock) { 81 | //再判断一次是否是初始值,因为可能多个线程在同步代码块处等待 82 | val _v2 = _value 83 | if (_v2 !== UNINITIALIZED_VALUE) { 84 | @Suppress("UNCHECKED_CAST") (_v2 as T) 85 | } else { 86 | //执行初始化代码(initializer),初始化逻辑从外面传进来的 87 | val typedValue = initializer!!() 88 | _value = typedValue 89 | initializer = null 90 | typedValue 91 | } 92 | } 93 | } 94 | } 95 | */ 96 | 97 | fun main(args: Array) { 98 | println(DelegatedProperty().friends) 99 | 100 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/delegated/DelegatedPropertyByMap.kt: -------------------------------------------------------------------------------- 1 | package delegated 2 | 3 | /** 4 | * 5 | * @author kumushuoshuo 6 | * @github https://github.com/chiclaim/ 7 | */ 8 | class DelegatedPropertyByMap(val map: Map) { 9 | val name: String? by map 10 | val age: Int by map 11 | } 12 | 13 | fun main() { 14 | val delegate = DelegatedPropertyByMap(hashMapOf("age" to 12)) 15 | println(delegate.age) 16 | //println(delegate.name) 17 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/delegated/DelegatedPropertyLazyMode.kt: -------------------------------------------------------------------------------- 1 | package delegated 2 | 3 | import tutorials.lesson10.println 4 | import kotlin.concurrent.thread 5 | 6 | class DelegatedProperty2 { 7 | val friends by lazy(LazyThreadSafetyMode.PUBLICATION) { 8 | println("init ------${Thread.currentThread().name}") 9 | loadFriendList() 10 | } 11 | 12 | private fun loadFriendList(): String { 13 | Thread.sleep(10) 14 | return "kumushuoshsuo${Thread.currentThread().name}" 15 | } 16 | } 17 | 18 | fun main() { 19 | val d = DelegatedProperty2() 20 | repeat(30){ 21 | thread(name = "My thread${it}") { 22 | d.friends.println() 23 | } 24 | } 25 | 26 | Thread.sleep(5000) 27 | 28 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/delegated/DelegationPattern.kt: -------------------------------------------------------------------------------- 1 | package delegated 2 | 3 | /** 4 | * Desc: Kotlin 简化委托模式 演示 5 | * Created by Chiclaim on 2018/9/20. 6 | */ 7 | 8 | interface IAnimal { 9 | fun eat() 10 | fun run() 11 | } 12 | 13 | class Kangaroo : IAnimal { 14 | 15 | override fun eat() { 16 | println("eating grass ...") 17 | } 18 | 19 | override fun run() { 20 | println("jump...") 21 | } 22 | 23 | } 24 | 25 | class KangarooDelegate(private val kangaroo: Kangaroo = Kangaroo()) : IAnimal{ 26 | override fun eat() { 27 | kangaroo.eat() 28 | } 29 | 30 | override fun run() { 31 | kangaroo.run() 32 | } 33 | 34 | } 35 | 36 | //注意:如果使用val/var修饰了构造方法参数,记得要设置private,否则就暴露了被代理的对象了 37 | class KangarooDelegate2(private val kangaroo: Kangaroo = Kangaroo()) : IAnimal by kangaroo { 38 | 39 | //假如 需要对run方法进行增强改造 40 | // override fun run() { 41 | // kangaroo.run() 42 | // println("shout...") 43 | // } 44 | 45 | //kotlin会替我们生成其他代理方法,如 eat 方法 46 | /* 47 | public void eat() { 48 | this.kangaroo.eat(); 49 | } 50 | */ 51 | } 52 | 53 | fun main(args: Array) { 54 | val k = KangarooDelegate2() 55 | k.run() 56 | } 57 | 58 | /* 59 | class UserRepository constructor(val userSource: IUserSource) : IUserSource{ 60 | 61 | override fun login(telephone:String, code:String){ 62 | userSource.login(telephone,code) 63 | } 64 | 65 | override fun register(telephone:String, code:String){ 66 | userSource.register(telephone,code) 67 | } 68 | 69 | ...//省略其他业务 70 | } 71 | 72 | // 简化为: 73 | 74 | class UserRepository constructor(userSource: IUserSource) : IUserSource by userSource 75 | */ 76 | 77 | 78 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/generic/GenericVariance.kt: -------------------------------------------------------------------------------- 1 | package generic 2 | 3 | import generic.java_generic.bean.Apple 4 | import generic.java_generic.bean.Food 5 | import generic.java_generic.bean.Fruit 6 | import generic.java_generic.bean.Pear 7 | 8 | /** 9 | * Desc: Kotlin泛型协变(out)、逆变(in) 10 | * 11 | *

12 | * 13 | * 关于Java泛型的协变、逆变可以查看JavaGenericWildcardTest里面有详细的介绍 14 | * 15 | * Kotlin同样也有泛型的协变、逆变,他们之间的概念是一致的,但是在声明上有些差异: 16 | * 17 | * Java是在声明变量的时候声明泛型协变、逆变的,不能再声明类的时候声明泛型协变、逆变(如Collections.copy函数源码) 18 | * 19 | * Kotlin是在声明类的时候声明泛型协变和逆变的,然后在类里使用的泛型的时候就不用声明泛型协变了;也可以在声明变量的时候声明泛型协变 20 | * 21 | *

22 | * 23 | * 24 | * 25 | * Created by Chiclaim on 2018/10/10. 26 | */ 27 | 28 | 29 | fun takeFruit(fruits: List) { 30 | } 31 | 32 | 33 | fun testGenericNumber2(numbers: MutableList) { 34 | } 35 | 36 | fun main(args: Array) { 37 | val foods: List = listOf(Food(), Food()) 38 | val fruits: List = listOf(Fruit(), Fruit()) 39 | val apples: List = listOf(Apple(), Apple()) 40 | val pears: List = listOf(Pear(), Pear()) 41 | //public interface List 42 | //out修饰的泛型是 泛型协变 covariant 43 | //像这样的类或接口如List,称之为协变(covariant)类(接口) 44 | //和Java一样,协变泛型不能传递父类类型,只能传递Fruit或者它的子类 45 | //takeFruit(foods) 编译报错 46 | takeFruit(fruits) 47 | takeFruit(apples) 48 | takeFruit(pears) 49 | 50 | //------------------------------------- 51 | 52 | 53 | // 根据上面的介绍发现List是协变类 54 | // 我们在来看下MutableList是否是协变类 55 | val ints2: MutableList = mutableListOf(1, 3, 4) 56 | //并不能成功传递参数,所以MutableList并不是一个协变类(invariant) 57 | //testGenericNumber2(ints2) 58 | 59 | //------------------------------------- 60 | 61 | //我们分别来看下协变类List和非协变类MutableList的源码声明 62 | //在声明类的时候使用协变、逆变 63 | //Kotlin List是一个泛型协变 64 | //public interface List 65 | //MutableList是一个invariant 66 | //public interface MutableList : List 67 | 68 | 69 | //------------------------------------- 70 | val foodComparator = Comparator { e1, e2 -> 71 | e1.hashCode() - e2.hashCode() 72 | } 73 | val fruitComparator = Comparator { e1, e2 -> 74 | e1.hashCode() - e2.hashCode() 75 | } 76 | val appleComparator = Comparator { e1, e2 -> 77 | e1.hashCode() - e2.hashCode() 78 | } 79 | 80 | val list = listOf(Fruit(), Fruit(), Fruit(), Fruit()) 81 | //来看下sortedWith方法的声明sortedWith(comparator: Comparator) 82 | //Comparator声明成了逆变(contravariant),这和Java的泛型通配符super一样的 83 | //所以只能传递Fruit以及Fruit父类的Comparator 84 | list.sortedWith(foodComparator) 85 | list.sortedWith(fruitComparator) 86 | //list.sortedWith(appleComparator) 编译报错 87 | 88 | //掌握了Java泛型通配符,也会很快掌握Kotlin的泛型协变和逆变 89 | //不同的是:Java只能在声明变量用到泛型的地方使用泛型变异,称之为use-site variance 90 | //Kotlin不仅支持use-site variance还支持 declaration-site variance 91 | //declaration-site variance 就是在声明类的时候声明泛型变异,如上面使用的Kotlin List就是在定义类的时候声明泛型变异 92 | //在下面的copyData和sortedWith都是use-site variance,即在用到的时候定义泛型变异 93 | 94 | 95 | 96 | } 97 | 98 | //也可以在声明泛型变量的时候使用协变、逆变 99 | fun copyData(source: MutableList, 100 | destination: MutableList) { 101 | for (item in source) { 102 | destination.add(item) 103 | } 104 | } 105 | 106 | public fun sortedWith(comparator: Comparator) { 107 | 108 | } 109 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/generic/MyList.kt: -------------------------------------------------------------------------------- 1 | package generic 2 | 3 | /** 4 | * desc: 5 | * 6 | * Created by Chiclaim on 2019/01/01 7 | */ 8 | 9 | interface MyList : Collection { 10 | //泛型不允许当入参 11 | //public fun indexOf(element: E): Int 12 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/generic/java_generic/bean/Apple.java: -------------------------------------------------------------------------------- 1 | package generic.java_generic.bean; 2 | 3 | //苹果 4 | public class Apple extends Fruit { 5 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/generic/java_generic/bean/Food.java: -------------------------------------------------------------------------------- 1 | package generic.java_generic.bean; 2 | 3 | //食物 4 | public class Food { 5 | 6 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/generic/java_generic/bean/Fruit.java: -------------------------------------------------------------------------------- 1 | package generic.java_generic.bean; 2 | 3 | //水果类 4 | public class Fruit extends Food { 5 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/generic/java_generic/bean/Pear.java: -------------------------------------------------------------------------------- 1 | package generic.java_generic.bean; 2 | 3 | //梨子 4 | public class Pear extends Fruit { 5 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/generic/java_generic/bean/Plate.java: -------------------------------------------------------------------------------- 1 | package generic.java_generic.bean; 2 | 3 | /** 4 | * Desc: 5 | * 6 | *

7 | * Java Generic Wildcards 8 | * 9 | *

10 | * Created by Chiclaim on 2018/10/11. 11 | */ 12 | 13 | //定义一个`盘子`类 14 | public class Plate { 15 | 16 | private T item; 17 | 18 | public Plate(T t) { 19 | item = t; 20 | } 21 | 22 | public void set(T t) { 23 | item = t; 24 | } 25 | 26 | public T get() { 27 | return item; 28 | } 29 | 30 | } 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/generic/java_generic/res/generic_extends.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chiclaim/KotlinTutorials/1048a734514e300d6050fb3da1f0bd11c0f3be4d/kotlin-in-action/src/main/java/generic/java_generic/res/generic_extends.png -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/generic/java_generic/res/generic_super.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chiclaim/KotlinTutorials/1048a734514e300d6050fb3da1f0bd11c0f3be4d/kotlin-in-action/src/main/java/generic/java_generic/res/generic_super.png -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/higher_order_function/ControlFlowInHighOrderFunc.kt: -------------------------------------------------------------------------------- 1 | package higher_order_function 2 | 3 | import base.Person 4 | 5 | /** 6 | * Desc: 7 | * Created by Chiclaim on 2018/10/8. 8 | */ 9 | fun lookForChiclaim(people: List) { 10 | for (person in people) { 11 | if (person.name == "chiclaim") { 12 | println("Found!") 13 | return 14 | } 15 | } 16 | println("chiclaim is not found") 17 | } 18 | 19 | fun lookForChiclaim2(people: List) { 20 | people.forEach { 21 | if (it.name == "chiclaim") { 22 | println("Found!") 23 | return 24 | } 25 | } 26 | println("chiclaim is not found") 27 | } 28 | 29 | //这里会隐含一个lambda标签,名字叫做 forEach 30 | fun lookForChiclaim3(people: List) { 31 | people.forEach { 32 | if (it.name == "chiclaim") { 33 | return@forEach 34 | } 35 | } 36 | println("chiclaim might be somewhere") 37 | } 38 | 39 | //也可以自定义lambda标签名字 40 | fun lookForChiclaim4(people: List) { 41 | people.forEach label@{ 42 | if (it.name == "chiclaim") { 43 | return@label 44 | } 45 | } 46 | println("chiclaim might be somewhere") 47 | } 48 | 49 | //lambda中使用label来return的方式,在有多个return表达式的时候,不好维护,可以使用匿名函数的方式 50 | //anonymous function 51 | //匿名函数默认是 local return 52 | fun lookForChiclaim5(people: List) { 53 | people.forEach(fun(person) { 54 | if (person.name == "chiclaim") return 55 | println("${person.name} is not chiclaim") 56 | }) 57 | } 58 | 59 | fun main(args: Array) { 60 | val list = listOf(Person("johnny"), Person("chiclaim"), Person("jack")) 61 | lookForChiclaim(list) 62 | lookForChiclaim2(list) 63 | lookForChiclaim3(list) 64 | lookForChiclaim4(list) 65 | lookForChiclaim5(list) 66 | 67 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/higher_order_function/FunctionTypeWithReceiver.kt: -------------------------------------------------------------------------------- 1 | package higher_order_function 2 | 3 | /* 4 | * Function types with receiver 5 | * @author kumushuoshuo 6 | * @github https://github.com/chiclaim/ 7 | */ 8 | 9 | public inline fun T.apply3(block: Int.() -> Unit): T { 10 | // Function types with receiver 11 | // block: Int.() -> Unit 12 | // 相当于 Int 类上扩展了一个名为 block 的函数类型 13 | // 所以可以使用整型来调用这个 block 14 | // 直接调用 block 会报错,需要一个 receiver 来调用 15 | 1.block() 16 | return this 17 | } 18 | public inline fun T.also2(block: (T) -> Unit): T { 19 | block(this) 20 | return this 21 | } 22 | fun main() { 23 | "".apply { 24 | 25 | } 26 | "".apply3 { 27 | // this 就是 1 28 | println("apply3 receiver = $this") 29 | } 30 | 31 | // public inline fun with(receiver: T, block: T.() -> R): R 32 | // public inline fun T.apply(block: T.() -> Unit): T 33 | // public inline fun T.also(block: (T) -> Unit): T 34 | // public inline fun T.let(block: (T) -> R): R 35 | // public inline fun run(block: () -> R): R 36 | // public inline fun T.run(block: T.() -> R): R 37 | 38 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/higher_order_function/InlineFunction.kt: -------------------------------------------------------------------------------- 1 | package higher_order_function 2 | 3 | import java.util.concurrent.locks.Lock 4 | 5 | /** 6 | * Desc: 如果函数参数是lambda,通过inline修饰符来提高性能 7 | * 8 | * 在之前我们介绍到了lambda表达式一般会编译成内部类的形式, 意味着每使用一次lambda表达式都会产生一个额外的内部类 9 | * 10 | * 如果lambda表达式还使用了外面的变量,那么每次调用都会新建一个内部类对象,具体的可以查看:@see lambda/LambdaAsParameter 11 | * 12 | * 为了提高性能,避免上面提到的在使用lambda过程中产生的问题,通过inline修饰符来提高性能 13 | * 14 | * 在使用inline 函数的同时也会增加代码体积,我们可以把inline函数体的代码量通过抽取的方式使得inline函数变小 15 | * 16 | * Created by Chiclaim on 2018/10/8. 17 | */ 18 | 19 | //==============内联函数 starting============================== 20 | //内联函数在被调用的时候直接直接把方法体的逻辑拷贝到调用者里 21 | //需要注意两点: 22 | // 1,内联函数的参数lambda不能用遍历保存; 23 | // 2,内联函数的参数lambda只能传递给内联函数 24 | //否则编译器会提示:Illegal usage of inline-parameter 25 | inline fun synchronized(lock: Lock, action: () -> T): T { 26 | lock.lock() 27 | try { 28 | //return wrap(action) 29 | return action() 30 | } finally { 31 | lock.unlock() 32 | } 33 | } 34 | 35 | /*inline*/ fun wrap(action: () -> T): T { 36 | return action() 37 | } 38 | 39 | fun test(lock: Lock) { 40 | println("Before sync") 41 | synchronized(lock) { 42 | println("Action") 43 | } 44 | println("After sync") 45 | } 46 | //==============ending=============================== 47 | 48 | 49 | //==============非内联函数对比 starting============================= 50 | //下面是非内联函数的调用,下面是通过内部类来实现的 51 | fun synchronized2(lock: Lock, action: () -> T): T { 52 | lock.lock() 53 | try { 54 | return action() 55 | } finally { 56 | lock.unlock() 57 | } 58 | } 59 | 60 | //内部类:higher_order_function/InlineFunctionKt$test2$1 61 | fun test2(lock: Lock) { 62 | println("Before sync") 63 | synchronized2(lock) { 64 | println("Action") 65 | } 66 | println("After sync") 67 | } 68 | 69 | //内部类:higher_order_function/InlineFunctionKt$test3$1 70 | fun test3(lock: Lock) { 71 | println("Before sync") 72 | synchronized2(lock) { 73 | println("Action") 74 | } 75 | println("After sync") 76 | } 77 | //通过分析生成的class字节码,每调用一次非内联的以lambda为参数的函数都会生成一个内部类 78 | //上面我们在test2和test3方法里分别调用了一次非内联函数synchronized2,然后生成了两个内部类: 79 | //内部类:higher_order_function/InlineFunctionKt$test2$1 80 | //内部类:higher_order_function/InlineFunctionKt$test3$1 81 | 82 | //==============ending============================= 83 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/higher_order_function/LambdaReceiverChangeTest.kt: -------------------------------------------------------------------------------- 1 | package higher_order_function 2 | 3 | fun main() { 4 | 5 | val any = Any() 6 | println(any) 7 | // 一般来说 lambda receiver 是调用该高阶函数对象 8 | any.apply { 9 | println(this) 10 | } 11 | 12 | // lambda receiver 并不是 `any` 对象,lambda receiver 已经被改变(apply3) 13 | val result = any.apply2 { 14 | println(this) // The obj of this has changed 15 | } 16 | println(result) 17 | 18 | 19 | } 20 | 21 | 22 | fun Any.apply2(block: Any.() -> Unit): String { 23 | return apply3(Any(), block) 24 | } 25 | 26 | // change lambda receiver 27 | fun apply3(r: R, block: R.() -> Unit): String { 28 | block(r) 29 | return r.toString() 30 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/higher_order_function/ScopeFunctions.kt: -------------------------------------------------------------------------------- 1 | package higher_order_function 2 | 3 | 4 | /** 5 | * 6 | * @author kumushuoshuo 7 | * @github https://github.com/chiclaim/ 8 | */ 9 | 10 | fun main() { 11 | 12 | // public inline fun with(receiver: T, block: T.() -> R): R 13 | // public inline fun T.apply(block: T.() -> Unit): T 14 | // public inline fun T.also(block: (T) -> Unit): T 15 | // public inline fun T.let(block: (T) -> R): R 16 | // public inline fun run(block: () -> R): R 17 | // public inline fun T.run(block: T.() -> R): R 18 | 19 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/higher_order_function/UsingFuncInJava.java: -------------------------------------------------------------------------------- 1 | package higher_order_function; 2 | 3 | import kotlin.jvm.functions.Function2; 4 | 5 | /** 6 | * Desc: 在Java中使用高阶函数 7 | * Created by Chiclaim on 2018/10/8. 8 | */ 9 | public class UsingFuncInJava { 10 | 11 | public static void main(String[] args) { 12 | 13 | //使用lambda的方式 14 | HigherOrderFuncKt.process(11, 2, (i1, i2) -> i1 + i2); 15 | 16 | //使用内部类的方式 17 | HigherOrderFuncKt.process(11, 2, new Function2() { 18 | 19 | @Override 20 | public Integer invoke(Integer i1, Integer i2) { 21 | return i1 * i2; 22 | } 23 | }); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/inline/InlineTest.kt: -------------------------------------------------------------------------------- 1 | package inline 2 | 3 | import kotlin.math.max 4 | 5 | /** 6 | * inline、noinline、crossinline 7 | * 8 | * 1. inline 基本原理 9 | * 2. 调用 inline 高阶函数,传入的 lambda 体使用外部变量和不使用外部变量的情况 10 | * 3. noinline 基本原理 11 | * 4. noinline 的作用 12 | * 5. inline 与 return 13 | * 6. crossinline 14 | */ 15 | class InlineTest { 16 | 17 | var age = 18 18 | 19 | // 在普通方法中添加 inline 没有意义 20 | // Expected performance impact from inlining is insignificant. Inlining works best for functions with parameters of functional types 21 | // inline 关键字主要用于高阶函数 22 | inline fun inlineFun() { 23 | println("from inlineFun") 24 | max(1, 2) 25 | } 26 | 27 | private fun proxy(action: () -> Unit) { 28 | println("start logging") 29 | action.invoke() 30 | println("end logging") 31 | } 32 | 33 | fun invokeProxy() { 34 | proxy { 35 | //age = 11 36 | println("eating") 37 | } 38 | } 39 | 40 | // 高阶函数也不能无脑加 inline,同时要考虑函数大小问题,尽可能让inline函数代码行数变小 41 | private inline fun proxyInline(action: () -> Unit) { 42 | println("start logging") 43 | action.invoke() 44 | println("end logging") 45 | } 46 | 47 | fun invokeProxyInline() { 48 | proxyInline { 49 | println("eating") 50 | } 51 | } 52 | 53 | /** 54 | * action 进行内联,action2 内联 55 | */ 56 | private inline fun proxyInline2(action: () -> Unit, noinline action2: () -> Unit) { 57 | println("start logging") 58 | action.invoke() 59 | println("end logging") 60 | action2.invoke() 61 | } 62 | 63 | fun invokeProxyInline2() { 64 | proxyInline2({ 65 | println("eating...") 66 | }, { 67 | println("eating...2") 68 | }) 69 | } 70 | 71 | // 那 oninline 有啥用,我们将 proxyInline2 改一改 72 | // 如果把 action2 的 online 去掉则报错,不能将内联的 action2 作为参数传递给高阶函数 73 | // 很好理解,因为如果 action2 被内联了,编译后,就变成了代码片段块了,目前只能使用(内部)类来表示代码块,所以 action2 不能被内联 74 | private inline fun proxyInline3(action: () -> Unit, noinline action2: () -> Unit) { 75 | println("start logging") 76 | action.invoke() 77 | println("end logging") 78 | cleanResource(action2) 79 | } 80 | 81 | private fun cleanResource(execution: () -> Unit) { 82 | execution.invoke() 83 | println("cleaning resource1") 84 | println("cleaning resource2") 85 | } 86 | 87 | fun invokeProxyInline3() { 88 | proxyInline2({ 89 | println("eating...") 90 | }, { 91 | println("eating...2") 92 | }) 93 | } 94 | 95 | 96 | private inline fun proxyInline4(action: () -> Unit) { 97 | println("start logging") 98 | action.invoke() 99 | println("end logging") 100 | } 101 | 102 | 103 | fun invokeProxyInline4() { 104 | proxyInline4 { 105 | println("eating...") 106 | // 在 lambda 中使用 return,该函数必须是 inline 107 | return 108 | } 109 | } 110 | 111 | 112 | private fun wrap(action: () -> Unit) { 113 | action.invoke() 114 | } 115 | 116 | private inline fun proxyInline5(action: () -> Unit) { 117 | println("start logging") 118 | wrap { 119 | // Can't inline 'action' here: it may contain non-local returns. Add 'crossinline' modifier to parameter declaration 'action' 120 | // action.invoke() 121 | } 122 | println("end logging") 123 | } 124 | 125 | private inline fun proxyInline6(crossinline action: () -> Unit) { 126 | println("start logging") 127 | wrap { 128 | action() 129 | } 130 | println("end logging") 131 | } 132 | 133 | 134 | fun invokeProxyInline6() { 135 | proxyInline6 { 136 | println("eating...") 137 | // 使用 crossinline 修饰的 lambda 不允许使用 return 138 | // return 139 | } 140 | } 141 | 142 | } 143 | 144 | fun main() { 145 | // InlineTest().invokeProxyInline4() 146 | InlineTest().invokeProxyInline6() 147 | } 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/lambda/Button.java: -------------------------------------------------------------------------------- 1 | package lambda; 2 | 3 | /** 4 | * desc: 5 | *

6 | * Created by Chiclaim on 2018/12/31 7 | */ 8 | 9 | public class Button { 10 | public void setOnClickListener(OnClickListener listener) { 11 | listener.click(); 12 | } 13 | 14 | public void setCallback(KotlinInterface callback) { 15 | callback.call(); 16 | } 17 | 18 | public interface OnClickListener { 19 | void click(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/lambda/FunctionalInterface.java: -------------------------------------------------------------------------------- 1 | package lambda; 2 | 3 | /** 4 | * desc: 5 | *

6 | * Created by Chiclaim on 2018/12/31 7 | */ 8 | 9 | public class FunctionalInterface { 10 | 11 | public static void main(String[]args){ 12 | Button button = new Button(); 13 | button.setOnClickListener(new Button.OnClickListener() { 14 | @Override 15 | public void click() { 16 | System.out.println("click 1"); 17 | } 18 | }); 19 | 20 | button.setOnClickListener(new Button.OnClickListener() { 21 | @Override 22 | public void click() { 23 | System.out.println("click 2"); 24 | } 25 | }); 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/lambda/FunctionalInterfaceTest.kt: -------------------------------------------------------------------------------- 1 | package lambda 2 | 3 | /** 4 | * desc: 5 | * 6 | * Created by Chiclaim on 2018/12/31 7 | */ 8 | 9 | fun main(args: Array) { 10 | val button = Button() 11 | var count = 0 12 | button.setOnClickListener { 13 | println("click ${++count}") 14 | } 15 | 16 | button.setOnClickListener { 17 | println("click ${++count}") 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/lambda/FunctionalInterfaceTest2.kt: -------------------------------------------------------------------------------- 1 | package lambda 2 | 3 | /** 4 | * desc: 5 | * 6 | * Created by Chiclaim on 2018/12/31 7 | */ 8 | 9 | fun main(args: Array) { 10 | val button = Button() 11 | val listener = Button.OnClickListener { 12 | println("click event") 13 | } 14 | button.setOnClickListener(listener) 15 | button.setOnClickListener(listener) 16 | 17 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/lambda/JavaLambdaModifyVariable.java: -------------------------------------------------------------------------------- 1 | package lambda; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | /** 7 | * desc: 在lambda中不能修改lambda外面的变量值 8 | *

9 | * Java Lambda底层是使用匿名内部来实现的,所以在Lambda里无法修改外面的变量值 10 | *

11 | * Created by Chiclaim on 2018/09/22 12 | */ 13 | 14 | public class JavaLambdaModifyVariable { 15 | private static void printGoods(String prefix, List goods) { 16 | int count = 0; 17 | goods.forEach(value -> { 18 | //不可修改, Kotlin的lambda可以 19 | //count++; 20 | System.out.println(prefix + " " + value); 21 | } 22 | ); 23 | } 24 | 25 | public static void main(String[] args) { 26 | printGoods("china", Arrays.asList("telephone", "tv")); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/lambda/KotlinInterface.kt: -------------------------------------------------------------------------------- 1 | package lambda 2 | 3 | /** 4 | * desc: 5 | * 6 | * Created by Chiclaim on 2018/12/31 7 | */ 8 | 9 | interface KotlinInterface { 10 | fun call() 11 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/lambda/KotlinLambdaModifyVariable.kt: -------------------------------------------------------------------------------- 1 | package lambda 2 | 3 | /** 4 | * desc: 修改Lambda外部的变量 演示 5 | * 6 | * Created by Chiclaim on 2018/09/22 7 | */ 8 | 9 | //----forEach底层是通过iterator来遍历的,并不是通过内部类来实现的,所以可以修改lambda外面的变量 10 | fun printGoods(prefix: String, goods: List) { 11 | var count = 0 12 | goods.forEach { goodName -> 13 | count++ 14 | println("$prefix $goodName") 15 | } 16 | println("goods count: $count") 17 | } 18 | 19 | //---- 下面的例子把Lambda赋值给变量inc,由于在lambda中没有使用额外的参数,底层是使用Function0来实现的 20 | //在下面的lambda底层是通过匿名内部类来实现的,我们知道内部类是修改不了外面的变量的,那么它是如何修改外面的counter变量呢? 21 | //通过把外面的变量包装一层,修改的时候,通过包装对象来修改,然后返回修改后的变量值 22 | //在Kotlin中通过Ref包装类,如果是整型则是IntRef,如果是复杂类型则是ObjectRef 23 | fun printCount() { 24 | 25 | var counter = 0 26 | 27 | //把Lambda赋值给变量 28 | val inc = { 29 | ++counter 30 | } 31 | 32 | println(inc()) 33 | 34 | } 35 | /* 36 | public static final void printCount() { 37 | final IntRef counter = new IntRef(); 38 | counter.element = 0; 39 | Function0 inc = (Function0)(new Function0() { 40 | public Object invoke() { 41 | return this.invoke(); 42 | } 43 | 44 | public final int invoke() { 45 | IntRef var10000 = counter; 46 | ++counter.element; 47 | return var10000.element; 48 | } 49 | }); 50 | int var2 = ((Number)inc.invoke()).intValue(); 51 | System.out.println(var2); 52 | } 53 | 54 | */ 55 | 56 | fun main(args: Array) { 57 | printGoods("china", listOf("telephone", "tv")) 58 | 59 | printCount() 60 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/lambda/LambdaAsParameter.kt: -------------------------------------------------------------------------------- 1 | package lambda 2 | 3 | /** 4 | * desc: lambda作为方法参数演示和原理分析 5 | * 6 | * Created by Chiclaim on 2018/09/24 7 | */ 8 | 9 | fun postDelay(runnable: Runnable) { 10 | runnable.run() 11 | } 12 | 13 | fun postDelay0(delay: Long, runnable: Runnable) { 14 | runnable.run() 15 | } 16 | 17 | inline fun postDelay1(delay: Long, runnable: () -> Unit) { 18 | runnable() 19 | } 20 | 21 | fun postDelay2(delay: Long, runnable: () -> Unit) { 22 | runnable() 23 | } 24 | 25 | //lambda作为参数,不能重载postDelay2 26 | //fun postDelay2(delay: Long, callable: () -> Unit) { 27 | // callable() 28 | //} 29 | 30 | //Applying an explicit SAM constructor 31 | //可以使用SAM constructor来避免Lambda作为参数无法重载的影响 32 | fun postDelay0(delay: Long, callable: _Runnable) { 33 | callable.run() 34 | } 35 | 36 | //函数返回类型是functional interface 37 | fun createAllDoneRunnable(): Runnable { 38 | //把lambda显示转换成函数接口(functional interface) 39 | return Runnable { println("All done!") } 40 | } 41 | 42 | 43 | fun main(args: Array) { 44 | 45 | //不允许将lambda当作参数进行传递 46 | //虽然Runnable是Java的Functional interface 47 | //但是postDelay方法使用kotlin定义的 48 | /*postDelay{ 49 | println("postDelay") 50 | }*/ 51 | 52 | //也不允许将lambda当作参数进行传递 53 | //因为KotlinInterface是Kotlin定义的 54 | /*Button().setCallback{ 55 | 56 | }*/ 57 | 58 | 59 | //创建一个实现了Runnable接口的内部类。 60 | //下面lambda没有访问外部的任何变量,所以不管postDelay触发多少遍,只会有一个Runnable对象 61 | //因为这个runnable对象是该内部类的常量 62 | postDelay0(1000, Runnable { 63 | println("postDelay0") 64 | }) 65 | 66 | //如果再调用一次postDelay会怎样?会创建一个和上面一样的实现了Runnable接口的内部类 67 | //调用postDelay0方法传入的runnable参数,就是该内部类的对象 68 | //由此可见有多少个lambda,就会有多少个内部类 69 | postDelay0(1000, Runnable { 70 | println("postDelay0 another") 71 | }) 72 | 73 | //但是如果该方法是内联函数(inline),则不会创建内部类 74 | postDelay1(1000) { 75 | println("inline postDelay1") 76 | } 77 | 78 | val flag = 10 79 | //下面的lambda访问了外部的flag变量,postDelay2方法调用一次便创建一个lambda对象 80 | postDelay2(1500) { 81 | println("postDelay2 $flag") 82 | } 83 | 84 | //------------可以ji结合class字节码来分析 85 | } 86 | 87 | interface _Runnable { fun run() 88 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/lambda/LambdaToVariableTest.kt: -------------------------------------------------------------------------------- 1 | package lambda 2 | 3 | /** 4 | * desc: 把Lambda赋值给一个变量 5 | * 6 | * Created by Chiclaim on 2018/09/22 7 | */ 8 | 9 | //最多支持22参数 对应的处理类是 Function22 10 | 11 | // N -> FunctionN 12 | 13 | class LambdaToVariableTest { 14 | 15 | private val base = 10 16 | 17 | val sum = { x: Int, y: Int, z: Int -> 18 | x + y + z + base 19 | } 20 | } 21 | 22 | fun main(args: Array) { 23 | val test = LambdaToVariableTest() 24 | println(test.sum(12, 10, 15)) 25 | } 26 | 27 | /* 28 | //除了要看编译后对应的Java代码,还需要分析其编译后生成的class字节码文件 29 | //如下面的这句代码: sum = (Function3)null.INSTANCE; 就问题了,所以Kotlin插件反编译出来的Java代码不是很完全 30 | 31 | public final class LambdaToVariableTestKt { 32 | @NotNull 33 | private static final Function3 sum; 34 | 35 | @NotNull 36 | public static final Function3 getSum() { 37 | return sum; 38 | } 39 | 40 | public static final void main(@NotNull String[] args) { 41 | Intrinsics.checkParameterIsNotNull(args, "args"); 42 | int var1 = ((Number)sum.invoke(12, 10, 15)).intValue(); 43 | System.out.println(var1); 44 | } 45 | 46 | static { 47 | sum = (Function3)null.INSTANCE; 48 | } 49 | } 50 | 51 | 52 | 53 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/lambda/LambdaWithReceiver.kt: -------------------------------------------------------------------------------- 1 | package lambda 2 | 3 | /** 4 | * Desc: with、apply、run函数 Lambda receiver 演示 5 | * Created by Chiclaim on 2018/9/25. 6 | */ 7 | 8 | 9 | //with函数有两个参数,一个是receiver 一个是lambda表达式。传递lambda参数,一般放在外面 10 | //此时lambda receiver就是with的第一个参数 11 | //使用with函数,调用receiver对象的方法时,可以很的省略这个对象,直接调用。如下面的append方法 12 | fun alphabet() = with(StringBuilder()) { 13 | for (letter in 'A'..'Z') { 14 | append(letter) 15 | } 16 | append("\nNow I know alphabet!").toString() 17 | } 18 | 19 | 20 | //apply函数是一个扩展函数 21 | //此时lambda receiver是调用apply函数的对象 22 | //使用apply函数可以创建对象后很方便地进行初始化操作 23 | fun alphabet2() = StringBuilder().apply { 24 | for (letter in 'A'..'Z') { 25 | append(letter) 26 | } 27 | append("\nNow I know the alphabet!") 28 | } 29 | 30 | fun alphabet3() = StringBuilder().run { 31 | for (c in 'A'..'Z') { 32 | append(c) 33 | } 34 | append("\nNow I know the alphabet!") 35 | } 36 | 37 | 38 | fun main(args: Array) { 39 | println(alphabet()) 40 | println(alphabet2()) 41 | println(alphabet3()) 42 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/lambda/MemberReferenceTest.kt: -------------------------------------------------------------------------------- 1 | package lambda 2 | 3 | 4 | /** 5 | * desc: Lambda member reference (variable、method) 6 | * 7 | * Created by Chiclaim on 2018/09/22 8 | */ 9 | 10 | class MemberReference { 11 | 12 | fun variableReference() { 13 | 14 | val age = Person::age 15 | 16 | //和上面功能是一样的 17 | val age2 = { person: Person -> person.age } 18 | 19 | val ageValue = age(Person("yuzhiqiang", 18)) 20 | val ageValue2 = age2(Person("chiclaim", 18)) 21 | 22 | } 23 | 24 | fun sendEmail(person: Person, message: String) { 25 | println("send email...") 26 | } 27 | 28 | fun functionReference() { 29 | 30 | //通过匿名内部类(Function2)实现,在我们LambdaToVariableTest例子中底层不是通过匿名内部类 31 | //为啥要通过内部类?因为lambda表达式体里使用到了外面的sendEmail方法 32 | //如果表达式里对外没有任何引用,则底层不需要通过内部类来实现 33 | val action0 = { person: Person, message: String -> 34 | sendEmail(person, message) 35 | 36 | //如果仅有下面一句println,则底层不需要通过内部类来实现 37 | //println("${person.name} send email") 38 | } 39 | 40 | //和上面是等价的 41 | val action1 = ::sendEmail 42 | 43 | action0(Person("chiclaim", 18), "hello friend") 44 | action1(Person("chiclaim", 18), "hello friend") 45 | } 46 | } 47 | /* 48 | //-----------------匿名内部类方式实现的 49 | public final void functionReference() { 50 | Function2 action0 = (Function2)(new Function2() { 51 | public Object invoke(Object var1, Object var2) { 52 | this.invoke((Person)var1, (String)var2); 53 | return Unit.INSTANCE; 54 | } 55 | 56 | public final void invoke(@NotNull Person person, @NotNull String message) { 57 | Intrinsics.checkParameterIsNotNull(person, "person"); 58 | Intrinsics.checkParameterIsNotNull(message, "message"); 59 | MemberReference.this.sendEmail(person, message); 60 | } 61 | }); 62 | KFunction action = new Function2((MemberReference)this) { 63 | public Object invoke(Object var1, Object var2) { 64 | this.invoke((Person)var1, (String)var2); 65 | return Unit.INSTANCE; 66 | } 67 | 68 | public final void invoke(@NotNull Person p1, @NotNull String p2) { 69 | Intrinsics.checkParameterIsNotNull(p1, "p1"); 70 | Intrinsics.checkParameterIsNotNull(p2, "p2"); 71 | ((MemberReference)this.receiver).sendEmail(p1, p2); 72 | } 73 | 74 | public final String getName() { 75 | return "sendEmail"; 76 | } 77 | 78 | public final String getSignature() { 79 | return "sendEmail(Llambda/Person;Ljava/lang/String;)V"; 80 | } 81 | }; 82 | action0.invoke(new Person("chiclaim", 18), "hello friend"); 83 | ((Function2)action).invoke(new Person("chiclaim", 18), "hello friend"); 84 | } 85 | 86 | 87 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/lambda/Person.kt: -------------------------------------------------------------------------------- 1 | package lambda 2 | 3 | data class Person(var name: String, var age: Int) { 4 | lateinit var children: List 5 | } 6 | 7 | val list = listOf(Person("chiclaim", 18), Person("yuzhiqiang", 15), 8 | Person("johnny", 27), Person("clause", 190), 9 | Person("fin", 190)) 10 | 11 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/new_class/ClassCreate.kt: -------------------------------------------------------------------------------- 1 | package new_class 2 | 3 | /** 4 | * Desc: 属性的 getter和setter方法 演示 5 | * Created by Chiclaim on 2018/9/19. 6 | */ 7 | class Person3 { 8 | 9 | //可变属性 10 | var name: String? = null 11 | //不可变属性 12 | val age: Int = 0 13 | 14 | //如果使用private修饰,则不会有getter和setter方法 15 | //外面就无法访问该属性了 16 | private var gender: Int = -1 17 | } 18 | 19 | /* 20 | 21 | public final class Person3 { 22 | @Nullable 23 | private String name; 24 | private final int age; 25 | private int gender = -1; 26 | 27 | @Nullable 28 | public final String getName() { 29 | return this.name; 30 | } 31 | 32 | public final void setName(@Nullable String var1) { 33 | this.name = var1; 34 | } 35 | 36 | public final int getAge() { 37 | return this.age; 38 | } 39 | } 40 | 41 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/new_class/ClassPrimaryConstructor.kt: -------------------------------------------------------------------------------- 1 | package new_class 2 | 3 | /** 4 | * Desc: 自动生成构造方法和getter演示 5 | * Created by Chiclaim on 2018/9/19. 6 | */ 7 | class Person (val name: String) //只会生成name的getter方法 8 | 9 | /* 10 | 11 | -由于name属性不可修改,所以不提供name的setter方法 12 | 13 | -Kotlin声明的class默认是public final的 14 | 15 | public final class Person { 16 | @NotNull 17 | private final String name; 18 | 19 | @NotNull 20 | public final String getName() { 21 | return this.name; 22 | } 23 | 24 | public Person(@NotNull String name) { 25 | Intrinsics.checkParameterIsNotNull(name, "name"); 26 | super(); 27 | this.name = name; 28 | } 29 | } 30 | 31 | 32 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/new_class/ClassPrimaryConstructor2.kt: -------------------------------------------------------------------------------- 1 | package new_class 2 | 3 | /** 4 | * Desc: 构造方法和getter、setter演示 5 | * Created by Chiclaim on 2018/9/19. 6 | */ 7 | class Person2(var name: String) 8 | 9 | /* 10 | 11 | public final class Person2 { 12 | @NotNull 13 | private String name; 14 | 15 | @NotNull 16 | public final String getName() { 17 | return this.name; 18 | } 19 | 20 | public final void setName(@NotNull String var1) { 21 | Intrinsics.checkParameterIsNotNull(var1, ""); 22 | this.name = var1; 23 | } 24 | 25 | public Person2(@NotNull String name) { 26 | Intrinsics.checkParameterIsNotNull(name, "name"); 27 | super(); 28 | this.name = name; 29 | } 30 | } 31 | 32 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/new_class/ClassPrimaryConstructor3.kt: -------------------------------------------------------------------------------- 1 | package new_class 2 | 3 | /** 4 | * Desc: 构造方法属性加上 var/val 修饰 和不加 var/val 修饰的区别 演示 5 | * Created by Chiclaim on 2018/9/19. 6 | */ 7 | class Person4 constructor(var name: String) 8 | //和上面等价 class Person4 (var name: String) 9 | 10 | class Person4_ constructor(name: String) { 11 | 12 | } 13 | //和上面等价 class Person4_ (name: String) 14 | 15 | 16 | /* 17 | name加上var/val修饰,才会作为类的属性 18 | 19 | public final class Person4 { 20 | @NotNull 21 | private String name; 22 | 23 | @NotNull 24 | public final String getName() { 25 | return this.name; 26 | } 27 | 28 | public final void setName(@NotNull String var1) { 29 | Intrinsics.checkParameterIsNotNull(var1, ""); 30 | this.name = var1; 31 | } 32 | 33 | public Person4(@NotNull String name) { 34 | Intrinsics.checkParameterIsNotNull(name, "name"); 35 | super(); 36 | this.name = name; 37 | } 38 | } 39 | 40 | name没有加上var/val修饰,name只是构造方法参数名 41 | public final class Person4_ { 42 | public Person4_(@NotNull String name) { 43 | Intrinsics.checkParameterIsNotNull(name, "name"); 44 | super(); 45 | } 46 | } 47 | 48 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/new_class/ClassSecondaryConstructor.kt: -------------------------------------------------------------------------------- 1 | package new_class 2 | 3 | /** 4 | * Desc: 多个 Secondary Constructor 构造方法以及初始化代码块的执行实际有 演示 5 | * 6 | * Primary Constructor和Secondary Constructor对比 7 | * 8 | * Created by Chiclaim on 2018/9/19. 9 | */ 10 | 11 | //构造方法和class声明在同一行时,该构造方法被称之为 Primary Constructor 12 | //如果构造方法在类的内部声明,该构造方法被称之为 Secondary Constructor 13 | 14 | //Primary Constructor和 Secondary Constructor区别: 15 | //Primary Constructor 构造方法的参数如果有val/var修饰,那么该类会生成和该参数一样的属性,以及与之对应setter和getter(如果是var修饰会有getter和setter,val修饰只有getter) 16 | //Secondary Constructor 构造方法的参数不能用val/var属性 17 | 18 | // 19 | 20 | open class Person5(var bool:Boolean){ 21 | var name: String? = null 22 | var id: Int = 0 23 | 24 | 25 | constructor(name: String) : this(false) { 26 | this.name = name 27 | } 28 | 29 | constructor(id: Int) : this("chiclaim") { 30 | this.id = id 31 | } 32 | 33 | } 34 | 35 | 36 | /* 37 | public class Person5 { 38 | @Nullable 39 | private String name; 40 | private int id; 41 | 42 | @Nullable 43 | public final String getName() { 44 | return this.name; 45 | } 46 | 47 | public final void setName(@Nullable String var1) { 48 | this.name = var1; 49 | } 50 | 51 | public final int getId() { 52 | return this.id; 53 | } 54 | 55 | public final void setId(int var1) { 56 | this.id = var1; 57 | } 58 | 59 | public Person5(@NotNull String name) { 60 | Intrinsics.checkParameterIsNotNull(name, "name"); 61 | super(); 62 | System.out.println("init----------"); 63 | this.name = name; 64 | } 65 | 66 | public Person5(int id) { 67 | this("chiclaim"); 68 | this.id = id; 69 | } 70 | } 71 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/new_class/ClassSecondaryConstructorKt2.kt: -------------------------------------------------------------------------------- 1 | package new_class 2 | 3 | /** 4 | * Desc: 调用父类或者自身构造方法 演示 5 | * 6 | * Created by Chiclaim on 2018/9/19. 7 | */ 8 | 9 | 10 | class Person6 : Person5 { 11 | 12 | var height: Float = 0f 13 | 14 | constructor(name: String) : super(name) //使用super调用父类的构造方法 15 | 16 | constructor(height: Float) : this("anonymity") { //使用this调用本类的构造方法 17 | this.height = height 18 | } 19 | 20 | } 21 | 22 | fun main(args: Array) { 23 | val p = Person6(190f) 24 | System.out.println("name = ${p.name}, height = ${p.height}") 25 | } 26 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/new_class/Color.kt: -------------------------------------------------------------------------------- 1 | package new_class 2 | 3 | 4 | //枚举类 5 | 6 | enum class Color(val r: Int, val g: Int, val b: Int ){ //枚举常量属性 7 | 8 | // 定义枚举常量对象 9 | RED(255, 0, 0), ORANGE(255, 165, 0), 10 | YELLOW(255, 255, 0), GREEN(0, 255, 0), 11 | BLUE(0, 0, 255), INDIGO(75, 0, 130), 12 | VIOLET(238, 130, 238); //最后一个枚举对象需要分号结尾 13 | 14 | // 在枚举类中定义函数 15 | fun rgb() = (r * 256 + g) * 256 + b 16 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/new_class/DataClassTest.kt: -------------------------------------------------------------------------------- 1 | package new_class 2 | 3 | /** 4 | * Desc: 自动生成 hashCode、equals、toString方法 5 | * Created by Chiclaim on 2018/9/20. 6 | */ 7 | 8 | data class Human(var id: String) { 9 | var name: String? = null 10 | } 11 | 12 | /* 13 | 14 | 会根据构造方法参数:id生成 hashCode、equals、toString、copy、componentN方法 15 | 16 | 此处省略对应的Java代码 17 | 18 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/new_class/InitBlock.kt: -------------------------------------------------------------------------------- 1 | package new_class 2 | 3 | /** 4 | * 5 | * @author kumushuoshuo 6 | * @github https://github.com/chiclaim/ 7 | */ 8 | 9 | 10 | open class Person7 { 11 | var name: String? = null 12 | var id: Int = 0 13 | 14 | 15 | constructor(name: String) { 16 | this.name = name 17 | } 18 | 19 | constructor(id: Int){ 20 | this.id = id 21 | } 22 | 23 | //构造对象的时候,init代码块只会被执行一次 24 | init { 25 | System.out.println("init----------") 26 | System.out.println("init----------") 27 | System.out.println("init----------") 28 | System.out.println("init----------") 29 | System.out.println("init----------") 30 | System.out.println("init----------") 31 | System.out.println("init----------") 32 | System.out.println("init----------") 33 | System.out.println("init----------") 34 | } 35 | 36 | } 37 | 38 | // 反编译 init block 竟然是代码拷贝 39 | 40 | /* 41 | 42 | // android 自定义 View 示例 43 | public class TestView extends View { 44 | 45 | public TestView(Context context) { 46 | super(context); 47 | init(); 48 | } 49 | 50 | public TestView(Context context, @Nullable AttributeSet attrs) { 51 | super(context, attrs); 52 | init(); 53 | } 54 | 55 | public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 56 | super(context, attrs, defStyleAttr); 57 | init(); 58 | } 59 | 60 | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 61 | public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { 62 | super(context, attrs, defStyleAttr, defStyleRes); 63 | init(); 64 | } 65 | 66 | private void init() { 67 | // .... 68 | } 69 | } 70 | 71 | */ 72 | 73 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/new_class/InnerClassTest.kt: -------------------------------------------------------------------------------- 1 | package new_class 2 | 3 | /** 4 | * desc: Kotlin内部类演示 5 | * 6 | * Created by Chiclaim on 2018/09/22 7 | */ 8 | 9 | class OuterClass { 10 | 11 | //和Java不同,在Kotlin中内部类默认是静态的,不持有外部类的引用 12 | class InnerStaticClass{ 13 | 14 | } 15 | 16 | //如果要声明非静态的内部类,需要加上inner关键字 17 | inner class InnerClass{ 18 | 19 | } 20 | } 21 | 22 | /* 23 | public static final class InnerStaticClass { 24 | } 25 | 26 | public final class InnerClass { 27 | } 28 | 29 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/new_class/InterfaceTest.kt: -------------------------------------------------------------------------------- 1 | package new_class 2 | 3 | /** 4 | * desc: Kotlin接口中包含变量和方法 演示 5 | * 6 | * Created by Chiclaim on 2018/09/20 7 | */ 8 | 9 | interface InterfaceTest { 10 | 11 | var count: Int 12 | 13 | fun plus(num: Int) { 14 | count += num 15 | } 16 | 17 | } 18 | 19 | class Impl : InterfaceTest { 20 | override var count: Int = 0 21 | 22 | override fun plus(num: Int) { 23 | super.plus(num) 24 | println("invoke plus") 25 | } 26 | } 27 | 28 | /* 29 | 30 | Java8之前的接口是不允许有变量和方法的,那么Kotlin是如何实现的呢? 31 | 32 | Kotlin 接口中的变量底层只是setter和setter方法 33 | Kotlin 接口中的方法并不是真的有方法体,底层也只有声明。只是在接口的内部新建一个静态内部类 34 | 内部类的里静态方法名就是我们在接口里声明有方法体的方法,静态方法有个额外的接口类型的参数,但是对我们开发者是透明的 35 | 接口里有方法体的方法在实现类里是不强制我们实现的,不是不需要,而是Kotlin已经替我们做了 36 | 37 | public interface InterfaceTest { 38 | int getCount(); 39 | void setCount(int var1); 40 | void plus(int var1); 41 | void test(); 42 | 43 | public static final class DefaultImpls { 44 | public static void plus(InterfaceTest $this, int num) { 45 | $this.setCount($this.getCount() + num); 46 | } 47 | 48 | public static void test(InterfaceTest $this) { 49 | String var1 = ""; 50 | System.out.print(var1); 51 | } 52 | } 53 | } 54 | 55 | public final class Impl implements InterfaceTest { 56 | private int count; 57 | 58 | public int getCount() { 59 | return this.count; 60 | } 61 | 62 | public void setCount(int var1) { 63 | this.count = var1; 64 | } 65 | 66 | public void plus(int num) { 67 | InterfaceTest.DefaultImpls.plus(this, num); 68 | } 69 | 70 | public void test() { 71 | InterfaceTest.DefaultImpls.test(this); 72 | } 73 | } 74 | 75 | 76 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/new_class/Java8InterfaceMethod.java: -------------------------------------------------------------------------------- 1 | package new_class; 2 | 3 | /** 4 | * @author kumushuoshuo 5 | * @github https://github.com/chiclaim/ 6 | */ 7 | public class Java8InterfaceMethod { 8 | 9 | public static void main(String[] args) { 10 | Male male = new YellowMale(); 11 | male.print(); 12 | 13 | Male.staticMethod(); 14 | } 15 | } 16 | 17 | 18 | interface Male { 19 | default void print(){ 20 | System.out.println("male..."); 21 | } 22 | default void print2(){ 23 | System.out.println("male2..."); 24 | } 25 | static void staticMethod(){ 26 | System.out.println("static..."); 27 | } 28 | } 29 | 30 | class YellowMale implements Male{ 31 | 32 | // 覆写 default 方法 33 | public void print(){ 34 | System.out.println("yellow male"); 35 | } 36 | 37 | /* default 只能在接口中使用 38 | default void dd(){ 39 | System.out.println("kumushuoshuo"); 40 | }*/ 41 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/new_class/SealedClassTest.kt: -------------------------------------------------------------------------------- 1 | package new_class 2 | 3 | /** 4 | * desc: sealed class 演示 5 | * 6 | * Created by Chiclaim on 2018/09/22 7 | */ 8 | 9 | 10 | /* 11 | 小结: 12 | 13 | 当我们使用when语句通常需要加else分支,如果when是判断某个复杂类型,如果该类型后面有新的子类,when语句就会走else分支 14 | 15 | sealed class就是用来解决这个问题的。 16 | 17 | 当when判断的是sealed class,那么不需要加else默认分支,如果有新的子类,编译器会通过编译报错的方式提醒开发者添加新分支,从而保证逻辑的完整性和正确性 18 | 19 | 需要注意的是,当when判断的是sealed class,千万不要添加else分支,否则有新子类编译器也不会提醒 20 | 21 | sealed class 在外部不能被继承,私有构造方法是私有的 22 | */ 23 | 24 | 25 | sealed class Expr { 26 | 27 | class Num(val value: Int) : Expr() 28 | class Sum(val left: Expr, val right: Expr) : Expr() 29 | 30 | } 31 | 32 | 33 | fun eval(e: Expr): Int = 34 | when (e) { 35 | is Expr.Num -> e.value 36 | is Expr.Sum -> eval(e.left) + eval(e.right) 37 | } 38 | 39 | //========================================================= 40 | 41 | open class Expr2; 42 | class Num2(val value: Int) : Expr2() 43 | class Sum2(val left: Expr2, val right: Expr2) : Expr2() 44 | 45 | fun eval2(e: Expr2): Int = 46 | when (e) { 47 | is Num2 -> e.value 48 | is Sum2 -> eval2(e.left) + eval2(e.right) 49 | else -> -1 50 | } 51 | 52 | 53 | fun main(args: Array) { 54 | val sum = eval(Expr.Sum(Expr.Num(1), Expr.Num(2))) 55 | println("sum = $sum") 56 | } 57 | 58 | 59 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/new_class/SingletonTest.kt: -------------------------------------------------------------------------------- 1 | package new_class 2 | 3 | /** 4 | * Desc: 单例类 演示 5 | * Created by Chiclaim on 2018/9/19. 6 | */ 7 | 8 | object Singleton 9 | 10 | /* 11 | public final class Singleton { 12 | public static final Singleton INSTANCE; 13 | 14 | private Singleton() { 15 | INSTANCE = (Singleton)this; 16 | } 17 | 18 | static { 19 | new Singleton(); 20 | } 21 | } 22 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/new_class/Test.java: -------------------------------------------------------------------------------- 1 | package new_class; 2 | 3 | import object_keyword.ObjectKeywordTest; 4 | import object_keyword.ObjectKeywordTest3; 5 | 6 | /** 7 | * @author kumushuoshuo 8 | * @github https://github.com/chiclaim/ 9 | */ 10 | public class Test { 11 | 12 | public static void main(String[] args) { 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/nullability/KotlinJavaNullability.kt: -------------------------------------------------------------------------------- 1 | package nullability 2 | 3 | /** 4 | * Desc: Kotlin和Java交互关于Null相关的问题 5 | * Created by Chiclaim on 2018/9/26. 6 | */ 7 | 8 | class UserActivity : UserView { 9 | var userPresenter = UserPresenter(this) 10 | 11 | 12 | override fun showFriendList(list: List) { 13 | list.forEachIndexed { index, user -> 14 | println("${index + 1}, $user") 15 | } 16 | } 17 | 18 | 19 | fun getFriendList() { 20 | println("-----------get remote friends") 21 | userPresenter.getRemoteFriendList() 22 | } 23 | 24 | fun getFriendList2() { 25 | println("-----------get local friends") 26 | userPresenter.getLocalFriendList() 27 | } 28 | 29 | } 30 | 31 | 32 | fun main(args: Array) { 33 | with(UserActivity()) { 34 | getFriendList() 35 | getFriendList2() //It will throw a Exception 36 | } 37 | } 38 | 39 | /* 40 | 41 | 42 | Kotlin会在用到的非空参数前做非空校验(底层自动为我们加上非空校验代码): 43 | Intrinsics.checkParameterIsNotNull(list, "list"); 44 | 45 | public void showFriendList(@NotNull List list) { 46 | Intrinsics.checkParameterIsNotNull(list, "list"); 47 | Iterable $receiver$iv = (Iterable)list; 48 | int index$iv = 0; 49 | Iterator var4 = $receiver$iv.iterator(); 50 | 51 | while(var4.hasNext()) { 52 | Object item$iv = var4.next(); 53 | int var10000 = index$iv++; 54 | User user = (User)item$iv; 55 | int index = var10000; 56 | String var8 = index + 1 + ", " + user; 57 | System.out.println(var8); 58 | } 59 | 60 | } 61 | 62 | 63 | */ 64 | 65 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/nullability/LateInitTest.kt: -------------------------------------------------------------------------------- 1 | package nullability 2 | 3 | /** 4 | * Desc: Late-initialized properties 属性延迟初始化 演示 5 | * Created by Chiclaim on 2018/9/18. 6 | */ 7 | class LateInitTest { 8 | 9 | private lateinit var username: String 10 | 11 | fun onCreate(name: String) { 12 | username = name 13 | 14 | //lateinit 属性不能设置为null,username = null; 15 | 16 | //lateinit 属性可用于依赖注入 17 | } 18 | } 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/nullability/NullabilityBasic.kt: -------------------------------------------------------------------------------- 1 | package nullability 2 | 3 | /** 4 | * Desc: ? 、?. 、:? 、!! 、let 使用演示 5 | * Created by Chiclaim on 2018/9/18. 6 | */ 7 | 8 | 9 | // 在Kotlin中声明的变量、属性、方法参数等默认是不能为空,如果允许为空需要在后面加上'?' 10 | 11 | //==========参数name不能为空=============== 12 | fun isEmpty0(name: String) = name.isEmpty() 13 | //======================================== 14 | 15 | 16 | //==========参数name可以为空=============== 17 | fun isEmpty1(name: String?) = name.isNullOrBlank() 18 | //======================================== 19 | 20 | 21 | //===========通过 ?. 操作符 来判空(可用于方法、属性)=============== 22 | //相当于 if(value!=null) return value.toUpperCase() return null 23 | fun toUpperCase(value: String?) = value?.toUpperCase() 24 | 25 | //和上面等价 26 | fun toUpperCase2(value: String?): String? { 27 | if (value == null) { 28 | return null 29 | } 30 | return value.toUpperCase() 31 | } 32 | //================================================================ 33 | 34 | 35 | //===============使用多个 ?. 链式调用================================ 36 | //底层相当于if判断嵌套 37 | fun getUpperCaseByte(value: String?) = value?.toUpperCase()?.toByte() 38 | //============================================================= 39 | 40 | 41 | //===========Elvis操作符 ?: 可用作判空的三目运算符,其他情况使用 if 实现三目运算符 42 | //底层就是通过三目运算符实现 age == null ? 0 : age 43 | fun safeAge(age: Int?): Int = age ?: 0 44 | //================================================================= 45 | 46 | 47 | //不要写这样的代码,因为getName()方法返回值是Any,可能返回Int也可能返回String 48 | fun getName(name: String?) = name ?: 1 49 | 50 | 51 | //===============非空断言 !! ======================================== 52 | //非空断言意思就是说 开发者保证这个变量一定不会为空,如果运行时变量为空,则抛出空指针异常 53 | fun ignoreNulls(str: String?) { 54 | println(str!!.length) 55 | } 56 | //================================================================== 57 | 58 | 59 | //===============let 函数判空======================================== 60 | fun console(message: String?) { 61 | 62 | message?.let { 63 | val result = it.substring(1) 64 | println(result) 65 | } 66 | 67 | message?.run { 68 | val result = substring(1) 69 | println(result) 70 | } 71 | 72 | message?.apply { 73 | val result = substring(1) 74 | println(result) 75 | } 76 | 77 | with(StringBuilder()) { 78 | for (letter in 'A'..'Z') { 79 | append(letter) 80 | } 81 | append("\nNow I know alphabet!").toString() 82 | } 83 | 84 | 85 | 86 | //相当于 87 | //if (message != null) { 88 | // println(it) 89 | //} 90 | 91 | message.run { 92 | println("run--------") 93 | 1 94 | } 95 | 96 | run { 97 | println("run--------") 98 | 1 99 | } 100 | } 101 | 102 | 103 | //================================================================== 104 | 105 | fun main(args: Array) { 106 | println(isEmpty0("chiclaim")) 107 | println(isEmpty1(null)) 108 | 109 | println(toUpperCase(null)) 110 | println(toUpperCase("chiclaim")) 111 | 112 | println("age---" + safeAge(null)) 113 | println("age---" + safeAge(99)) 114 | 115 | 116 | //getName()返回Integer 117 | println(getName(null).javaClass) 118 | //getName()返回String 119 | println(getName("chiclaim").javaClass) 120 | } 121 | 122 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/nullability/NullabilityExtensionFunc.kt: -------------------------------------------------------------------------------- 1 | package nullability 2 | 3 | /** 4 | * Desc: Null相关的扩展函数 5 | * Created by Chiclaim on 2018/9/26. 6 | */ 7 | 8 | //isNullOrBlank 9 | fun verifyUserInput(input: String?) { 10 | if (input.isNullOrBlank()) { 11 | println("Please fill in the required fields") 12 | return 13 | } 14 | println("inputted $input is valid") 15 | //..... 16 | } 17 | 18 | fun verifyUserInput2(input: String?) { 19 | if (input.isNullOrEmpty()) { 20 | println("Please fill in the required fields") 21 | return 22 | } 23 | println("inputted $input is valid") 24 | //..... 25 | } 26 | 27 | fun main(args: Array) { 28 | verifyUserInput(null) 29 | verifyUserInput("") 30 | verifyUserInput(" ") 31 | verifyUserInput("chiclaim") 32 | 33 | println("-------------------------------------") 34 | 35 | 36 | verifyUserInput2(null) 37 | verifyUserInput2("") 38 | verifyUserInput2(" ") 39 | verifyUserInput2("chiclaim") 40 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/nullability/User.kt: -------------------------------------------------------------------------------- 1 | package nullability 2 | 3 | /** 4 | * Created by dh on 2017/7/5. 5 | */ 6 | 7 | 8 | data class User(val nickname: String) 9 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/nullability/UserPresenter.java: -------------------------------------------------------------------------------- 1 | package nullability; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | /** 7 | * Desc: 8 | * Created by Chiclaim on 2018/9/26. 9 | */ 10 | public class UserPresenter { 11 | 12 | //The interface define with kotlin 13 | private final UserView friendView; 14 | 15 | public UserPresenter(UserView friendView) { 16 | this.friendView = friendView; 17 | } 18 | 19 | public void getRemoteFriendList() { 20 | List friends = requestFriendList(); 21 | friendView.showFriendList(friends); 22 | } 23 | 24 | public void getLocalFriendList() { 25 | List friends = getFriendList(); 26 | //因为 showFriendList方法参数定义为非空,但是friends变量可能为空 27 | //Java的编写的变量,对于Kotlin来说既可以用于nullable和non-nullable,所以可以传给Kotlin定义的参数不能为空的方法 28 | friendView.showFriendList(friends); 29 | } 30 | 31 | 32 | private List requestFriendList() { 33 | return Arrays.asList(new User("chiclaim"), new User("johnny"), 34 | new User("pony"), new User("jack")); 35 | } 36 | 37 | private List getFriendList() { 38 | return wrapList(); 39 | //return null; Don't return null directly , avoid showing warning tip by IDE 40 | } 41 | 42 | private List wrapList() { 43 | return null; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/nullability/UserView.kt: -------------------------------------------------------------------------------- 1 | package nullability 2 | 3 | /** 4 | * Desc: 5 | * Created by Chiclaim on 2018/9/26. 6 | */ 7 | interface UserView { 8 | 9 | fun showFriendList(list: List) 10 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/object_keyword/ObjectKeywordTest.kt: -------------------------------------------------------------------------------- 1 | package object_keyword 2 | 3 | /** 4 | * Desc: companion object里声明变量、常量 演示 5 | * Created by Chiclaim on 2018/9/20. 6 | */ 7 | 8 | class ObjectKeywordTest { 9 | companion object { 10 | //公共常量 11 | const val FEMALE: Int = 0 12 | const val MALE: Int = 1 13 | 14 | //私有常量 15 | val GENDER: Int = FEMALE 16 | 17 | //静态变量 18 | var username: String = "chiclaim" 19 | 20 | //静态方法 21 | fun run() { 22 | println("run...") 23 | } 24 | } 25 | 26 | } 27 | 28 | /* 29 | 30 | 私有常量和私有静态变量的访问统一通过ObjectKeywordTest的静态内部类Companion来访问 31 | 如果是kotlin代码访问私有常量或私有静态变量调用的时候不需要显示的通过Companion,为了方便底层已经为我们做了 32 | 如果是java代码访问私有常量或私有静态变量,则需要使用ObjectKeywordTest的静态内部类Companion 33 | 34 | 上面companion object 对应的Java代码: 35 | class ObjectKeywordTest { 36 | //公共常量 37 | public static final int FEMALE = 0; 38 | public static final int MALE = 1; 39 | //私有常量 40 | private static final int gender = 1; 41 | //静态变量 42 | @NotNull 43 | private static String username = "chiclaim"; 44 | 45 | public static final ObjectKeywordTest.Companion Companion = new ObjectKeywordTest.Companion((DefaultConstructorMarker)null); 46 | 47 | public static final class Companion { 48 | 49 | public final void run() { 50 | String var1 = "run..."; 51 | System.out.println(var1); 52 | } 53 | 54 | public final int getGENDER() { 55 | return ObjectKeywordTest.GENDER; 56 | } 57 | 58 | @NotNull 59 | public final String getUsername() { 60 | return ObjectKeywordTest.username; 61 | } 62 | 63 | public final void setUsername(@NotNull String var1) { 64 | Intrinsics.checkParameterIsNotNull(var1, ""); 65 | ObjectKeywordTest.username = var1; 66 | } 67 | 68 | private Companion() { 69 | } 70 | } 71 | } 72 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/object_keyword/ObjectKeywordTest2.kt: -------------------------------------------------------------------------------- 1 | package object_keyword 2 | 3 | /** 4 | * Desc: companion object里声明方法 演示 5 | * Created by Chiclaim on 2018/9/20. 6 | */ 7 | 8 | class ObjectKeywordTest2 { 9 | companion object { 10 | fun run() { 11 | println("run...") 12 | } 13 | } 14 | 15 | } 16 | 17 | /* 18 | 需要注意的是上面的run方法并不是一个static静态方法,只是让我们在调用的时候像静态方法(ObjectKeywordTest2.run()) 19 | 底层调用依然是通过ObjectKeywordTest2的静态内部类来访问的:ObjectKeywordTest2.Companion.run(); 20 | 21 | 对应的Java代码如下所示: 22 | public final class ObjectKeywordTest2 { 23 | public static final ObjectKeywordTest2.Companion Companion = new ObjectKeywordTest2.Companion((DefaultConstructorMarker)null); 24 | 25 | public static final class Companion { 26 | public final void run() { 27 | String var1 = "run..."; 28 | System.out.println(var1); 29 | } 30 | 31 | private Companion() { 32 | } 33 | } 34 | } 35 | 36 | 据此可得:在companion object中声明的方法、静态变量、私有常量都只能通过Companion访问 37 | 在companion object中声明的方法会放到静态内部类Companion中 38 | 39 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/object_keyword/ObjectKeywordTest3.kt: -------------------------------------------------------------------------------- 1 | package object_keyword 2 | 3 | /** 4 | * Desc: companion object 自定义名称 演示 5 | * Created by Chiclaim on 2018/9/20. 6 | */ 7 | 8 | class ObjectKeywordTest3 { 9 | companion object Cache { 10 | fun save2DB() { 11 | println("save data to database...") 12 | } 13 | 14 | fun save2Memory() { 15 | println("save data to memory...") 16 | } 17 | } 18 | 19 | 20 | } 21 | 22 | /* 23 | companion object对应的静态内部类名字默认是Companion 24 | 也可以通过companion object XXX来自定义自己想要的名字 25 | 26 | public final class ObjectKeywordTest3 { 27 | public static final ObjectKeywordTest3.Cache Cache = new ObjectKeywordTest3.Cache((DefaultConstructorMarker)null); 28 | public static final class Cache { 29 | public final void save2DB() { 30 | String var1 = "save data to database..."; 31 | System.out.println(var1); 32 | } 33 | 34 | public final void save2Memory() { 35 | String var1 = "save data to memory..."; 36 | System.out.println(var1); 37 | } 38 | 39 | private Cache() { 40 | } 41 | } 42 | } 43 | 44 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/object_keyword/ObjectKeywordTest4.kt: -------------------------------------------------------------------------------- 1 | package object_keyword 2 | 3 | 4 | /** 5 | * Desc: companion object 实现接口 演示 6 | * Created by Chiclaim on 2018/9/20. 7 | */ 8 | interface IAnimal { 9 | fun eat() 10 | } 11 | 12 | class ObjectKeywordTest4 { 13 | 14 | companion object : IAnimal { 15 | override fun eat() { 16 | println("eating apple") 17 | } 18 | } 19 | } 20 | 21 | fun feed(animal: IAnimal) { 22 | animal.eat() 23 | } 24 | 25 | fun main(args: Array) { 26 | feed(ObjectKeywordTest4)//实际传递的是静态对象 ObjectKeywordTest4.Companion 27 | } 28 | 29 | /* 30 | public static final void main(@NotNull String[] args) { 31 | feed((IAnimal)ObjectKeywordTest4.Companion); 32 | } 33 | 34 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/object_keyword/ObjectKeywordTest5.kt: -------------------------------------------------------------------------------- 1 | package object_keyword 2 | 3 | 4 | /** 5 | * Desc: companion object 函数扩展 演示 6 | * Created by Chiclaim on 2018/9/20. 7 | */ 8 | 9 | 10 | class ObjectKeywordTest5 { 11 | 12 | companion object { 13 | } 14 | 15 | 16 | } 17 | 18 | fun ObjectKeywordTest5.Companion.create(): ObjectKeywordTest5 { 19 | return ObjectKeywordTest5() 20 | } 21 | 22 | 23 | fun main(args: Array) { 24 | ObjectKeywordTest5.create() 25 | } 26 | /* 27 | 28 | public final class ObjectKeywordTest5 { 29 | public static final ObjectKeywordTest5.Companion Companion = new ObjectKeywordTest5.Companion((DefaultConstructorMarker)null); 30 | 31 | public static final class Companion { 32 | private Companion() { 33 | } 34 | } 35 | } 36 | 37 | public final class ObjectKeywordTest5Kt { 38 | @NotNull 39 | public static final ObjectKeywordTest5 create(@NotNull ObjectKeywordTest5.Companion $receiver) { 40 | Intrinsics.checkParameterIsNotNull($receiver, "$receiver"); 41 | return new ObjectKeywordTest5(); 42 | } 43 | 44 | public static final void main(@NotNull String[] args) { 45 | Intrinsics.checkParameterIsNotNull(args, "args"); 46 | create(ObjectKeywordTest5.Companion); 47 | } 48 | } 49 | 50 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/object_keyword/ObjectKeywordTest6.kt: -------------------------------------------------------------------------------- 1 | package object_keyword 2 | 3 | import java.awt.event.MouseAdapter 4 | import java.awt.event.MouseEvent 5 | import javax.swing.JLabel 6 | 7 | 8 | /** 9 | * Desc: object表达式 创建匿名内部类 演示 10 | * Created by Chiclaim on 2018/9/20. 11 | */ 12 | 13 | 14 | fun main(args: Array) { 15 | 16 | val jLabel = JLabel() 17 | 18 | jLabel.addMouseListener(object : MouseAdapter() { 19 | override fun mouseClicked(e: MouseEvent?) { 20 | super.mouseClicked(e) 21 | println("mouseClicked") 22 | } 23 | 24 | override fun mouseMoved(e: MouseEvent?) { 25 | super.mouseMoved(e) 26 | println("mouseMoved") 27 | } 28 | }) 29 | } 30 | 31 | /* 32 | 33 | 上面代码对应的Java代码: 34 | 35 | public static final void main(@NotNull String[] args) { 36 | Intrinsics.checkParameterIsNotNull(args, "args"); 37 | JLabel jLabel = new JLabel(); 38 | jLabel.addMouseListener((MouseListener)(new MouseAdapter() { 39 | public void mouseClicked(@Nullable MouseEvent e) { 40 | super.mouseClicked(e); 41 | String var2 = "mouseClicked"; 42 | System.out.println(var2); 43 | } 44 | 45 | public void mouseMoved(@Nullable MouseEvent e) { 46 | super.mouseMoved(e); 47 | String var2 = "mouseMoved"; 48 | System.out.println(var2); 49 | } 50 | })); 51 | } 52 | 53 | 54 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/operator_overloading/ArithmeticOperator.kt: -------------------------------------------------------------------------------- 1 | package operator_overloading 2 | 3 | /** 4 | * Desc: 算术符操作符重载 5 | * Created by Chiclaim on 2018/9/28. 6 | */ 7 | 8 | //算术符重载 函数和操作符的对应关系: 9 | // plus -> + 10 | // minus -> - 11 | // times -> * 12 | // div -> / 13 | // rem -> % 14 | 15 | 16 | 17 | //通过函数扩展进行操作符重载 18 | operator fun Point.minus(other: Point): Point { 19 | return Point(x - other.x, y - other.y) 20 | } 21 | 22 | fun main(args: Array) { 23 | val p1 = Point(10, 30) 24 | val p2 = Point(20, 30) 25 | println("plus: ${p1 + p2}") 26 | println("minus: ${p1 - p2}") 27 | println("times: ${p1 * p2}") 28 | println("div: ${p1 / p2}") 29 | 30 | } 31 | 32 | /* 33 | //使用重载的操作符,编译后最终也是调用对应的方法 34 | 35 | public static final void main(@NotNull String[] args) { 36 | Intrinsics.checkParameterIsNotNull(args, "args"); 37 | Point p1 = new Point(10, 30); 38 | Point p2 = new Point(20, 30); 39 | String var3 = "plus " + p1.plus(p2); 40 | System.out.println(var3); 41 | var3 = "minus " + minus(p1, p2); 42 | System.out.println(var3); 43 | var3 = "times " + p1.times(p2); 44 | System.out.println(var3); 45 | var3 = "div " + p1.div(p2); 46 | System.out.println(var3); 47 | } 48 | 49 | 50 | */ 51 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/operator_overloading/ComparisonOperator.kt: -------------------------------------------------------------------------------- 1 | package operator_overloading 2 | 3 | /** 4 | * Desc: 比较操作符重载 ==、!=、>、<、>=、<= 5 | * Created by Chiclaim on 2018/9/28. 6 | */ 7 | 8 | //equals() == 9 | //!equals() != 10 | //compareTo() >、<、>=、<= 11 | 12 | fun main(args: Array) { 13 | val p1 = Person("chiclaim", 20) 14 | val p2 = Person("pony", 20) 15 | println(p1 == p2) //p1.equals(p2) 16 | println(p1 > p2) //p1.compareTo(p2) > 0 17 | println(p1 >= p2) //p1.compareTo(p2) >= 0 18 | println(p1 < p2) //p1.compareTo(p2) < 0 19 | println(p1 <= p2) //p1.compareTo(p2) <= 0 20 | println(p1 != p2) // ! p1.equals(p2) 21 | 22 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/operator_overloading/ComponentOprerator.kt: -------------------------------------------------------------------------------- 1 | package operator_overloading 2 | 3 | /** 4 | * Desc: 解构操作符重载 5 | * Created by Chiclaim on 2018/9/30. 6 | */ 7 | 8 | 9 | operator fun Point.component1() = x 10 | operator fun Point.component2() = y 11 | 12 | 13 | fun getPoint(): Point { 14 | return Point(1, 2) 15 | } 16 | 17 | 18 | fun getMaxMin(): Pair { 19 | //省略获取最大值最小值的逻辑... 20 | 21 | val min: Int = 5 22 | val max: Int = 10 23 | return Pair(min, max) 24 | 25 | } 26 | 27 | fun main(args: Array) { 28 | val p1 = Point(10, 19) 29 | val (x, y) = p1 30 | println("x=$x , y=y$y") 31 | 32 | val (x1, y1) = getPoint() 33 | println("x=$x1 , y=y$y1") 34 | 35 | 36 | //解构操作符用于 集合遍历 37 | val map = hashMapOf("name" to "chiclaim", "address" to "hangzhou") 38 | for ((key, value) in map) { 39 | println("$key -> $value") 40 | } 41 | 42 | 43 | //集合最多支持声明5个变量 44 | val (v1, v2, v3, v4, v5) = listOf(1, 2, 3, 4, 5, 6) 45 | 46 | val (min, max) = getMaxMin() 47 | 48 | } 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/operator_overloading/CompoundAssignmentOperator.kt: -------------------------------------------------------------------------------- 1 | package operator_overloading 2 | 3 | /** 4 | * Desc: compound assignment operator 混合赋值操作符 5 | * Created by Chiclaim on 2018/9/28. 6 | */ 7 | 8 | //混合赋值操作符 函数和操作符的对应关系: 9 | // plusAssign -> += 10 | // minusAssign -> -= 11 | // timesAssign -> *= 12 | // divAssign -> /= 13 | // remAssign -> %= 14 | 15 | 16 | // compound assignment operator 首选保证备操作的属性是可以被修改的(mutable) 17 | //如下面的x,y属性是var修饰的 18 | 19 | operator fun Point.plusAssign(other: Point) { 20 | x += other.x 21 | y += other.y 22 | } 23 | 24 | operator fun Point.minusAssign(other: Point) { 25 | x -= other.x 26 | y -= other.y 27 | } 28 | 29 | operator fun Point.timesAssign(other: Point) { 30 | x *= other.x 31 | y *= other.y 32 | } 33 | 34 | operator fun Point.divAssign(other: Point) { 35 | x /= other.x 36 | y /= other.y 37 | } 38 | 39 | operator fun Point.remAssign(other: Point) { 40 | x %= other.x 41 | y %= other.y 42 | } 43 | 44 | 45 | fun main(args: Array) { 46 | val p1 = Point(10, 30) 47 | val p2 = Point(20, 30) 48 | 49 | //没有定义plusAssign 则会调用 plus方法 相当于 p1 = p1 + p2 50 | p1 += p2 51 | println("plusAssign: $p1") 52 | 53 | p1 -= p2 54 | println("minusAssign: $p1") 55 | 56 | p1 *= p2 57 | println("timesAssign: $p1") 58 | 59 | p1 /= p2 60 | println("divAssign: $p1") 61 | 62 | p1 %= p2 63 | println("remAssign: $p1") 64 | 65 | 66 | //p1 = p1 + p2 67 | //p1 += p2 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/operator_overloading/InOperator.kt: -------------------------------------------------------------------------------- 1 | package operator_overloading 2 | 3 | /** 4 | * Desc: in操作符 5 | * Created by Chiclaim on 2018/9/29. 6 | */ 7 | 8 | // a in c -> c.contains(a) 9 | // c in List/Array/CharSequence -> iterator() 10 | 11 | data class Rectangle(val upperLeft: Point, val lowerRight: Point) 12 | 13 | 14 | //until是一个中缀函数(infix) 15 | 16 | //10 until 20 --> 10 to 19 开区间(open range) 17 | //10..20 --> 10 to 20 闭区间(close range) 18 | 19 | operator fun Rectangle.contains(p: Point): Boolean { 20 | return p.x in (upperLeft.x until lowerRight.x) && 21 | (p.y in upperLeft.y until lowerRight.y) 22 | } 23 | 24 | fun main(args: Array) { 25 | val rect = Rectangle(Point(10, 10), Point(60, 60)) 26 | println(Point(20, 20) in rect) 27 | println(Point(5, 20) in rect) 28 | 29 | 30 | val a = 'c' in "chiclaim" //contains() 31 | println("----$a") 32 | 33 | for(value in "chiclaim"){//iterator() 34 | println(value) 35 | } 36 | 37 | val list = listOf(1,2,3) 38 | for (i in list){ 39 | 40 | } 41 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/operator_overloading/IndexOpertaor.kt: -------------------------------------------------------------------------------- 1 | package operator_overloading 2 | 3 | /** 4 | * Desc: 索引操作符重载 5 | * Created by Chiclaim on 2018/9/29. 6 | */ 7 | 8 | 9 | operator fun Point.get(index: Int): Int { 10 | return when (index) { 11 | 0 -> x 12 | 1 -> y 13 | else -> 14 | throw IndexOutOfBoundsException("Invalid coordinate $index") 15 | } 16 | } 17 | 18 | operator fun Point.get(propertyName: String): Int { 19 | return when (propertyName) { 20 | "x" -> x 21 | "y" -> y 22 | else -> 23 | throw IllegalArgumentException("Invalid propertyName $propertyName") 24 | } 25 | } 26 | 27 | operator fun Point.set(propertyName: String, value: Int) { 28 | when (propertyName) { 29 | "x" -> x = value 30 | "y" -> y = value 31 | else -> 32 | throw IllegalArgumentException("Invalid propertyName $propertyName") 33 | } 34 | } 35 | 36 | operator fun Point.set(index: Int, value: Int) { 37 | when (index) { 38 | 0 -> x = value 39 | 1 -> y = value 40 | else -> 41 | throw IllegalArgumentException("Invalid property index $index") 42 | } 43 | } 44 | 45 | fun main(args: Array) { 46 | val point = Point(100, 200) 47 | println("x=${point[0]}, y=${point[1]}") 48 | point["x"] = 500 49 | point[1] = 500 50 | println("x=${point["x"]}, y=${point["y"]}") 51 | 52 | 53 | val map = hashMapOf("chiclaim" to 28) //声明一个可变集合 54 | map["chiclaim"] = 18 //相当于 map.put("chiclaim", 18) 55 | println(map["chiclaim"]) //相当于 println(map.get("chiclaim")) 56 | } 57 | 58 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/operator_overloading/Person.kt: -------------------------------------------------------------------------------- 1 | package operator_overloading 2 | 3 | /** 4 | * Desc: 5 | * Created by Chiclaim on 2018/9/29. 6 | */ 7 | class Person(val name: String, val age: Int) : Comparable { 8 | override fun compareTo(other: Person): Int { 9 | //先比较age,如果age相等,在比较name 10 | //比较字段是可变参数,可以输入多个 11 | return compareValuesBy(this, other, Person::age, Person::name) 12 | } 13 | 14 | override fun equals(other: Any?): Boolean { 15 | val o = other as? Person 16 | return name == o?.name 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/operator_overloading/Point.kt: -------------------------------------------------------------------------------- 1 | package operator_overloading 2 | 3 | /** 4 | * 操作符重载需要的类 5 | */ 6 | class Point(var x: Int, var y: Int) { 7 | 8 | operator fun plus(other: Point): Point { 9 | return Point(x + other.x, y + other.y) 10 | } 11 | 12 | operator fun times(other: Point): Point { 13 | return Point(x * other.x, y * other.y) 14 | } 15 | 16 | operator fun div(other: Point): Point { 17 | return Point(x / other.x, y / other.y) 18 | } 19 | 20 | operator fun rem(other: Point): Point { 21 | return Point(x % other.x, y % other.y) 22 | } 23 | 24 | override fun toString(): String { 25 | return "Point[$x, $y]" 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/operator_overloading/RangeToOperator.kt: -------------------------------------------------------------------------------- 1 | package operator_overloading 2 | 3 | import java.time.LocalDate 4 | 5 | /** 6 | * Desc: ..操作符 7 | * Created by Chiclaim on 2018/9/29. 8 | */ 9 | 10 | //rangeTo -> .. 11 | //任何实现Comparable接口都可以使用 .. 操作符 12 | //in Ranges.kt 13 | //public operator fun > T.rangeTo(that: T): ClosedRange = ComparableRange(this, that) 14 | fun main(args: Array) { 15 | val nowDate = LocalDate.now() 16 | val vacation = nowDate..nowDate.plusDays(10) 17 | 18 | //class kotlin.ranges.ComparableRange 19 | println(vacation.javaClass) 20 | 21 | println(nowDate.plusWeeks(1) in vacation) 22 | 23 | 24 | for (i in (0..10)){ 25 | println(i) 26 | } 27 | 28 | 29 | val a = 0..10 30 | println(a.javaClass) //class kotlin.ranges.IntRange 31 | 32 | 33 | 34 | val personRange = Person("chiclaim",28)..Person("steve",56) 35 | println(personRange.javaClass) //class kotlin.ranges.ComparableRange 36 | 37 | val zucker = Person("zuckerberg",34) 38 | 39 | println(zucker in personRange) 40 | 41 | 42 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/operator_overloading/UnaryOperator.kt: -------------------------------------------------------------------------------- 1 | package operator_overloading 2 | 3 | import java.math.BigDecimal 4 | 5 | /** 6 | * Desc: 一元操作符 重载 7 | * Created by Chiclaim on 2018/9/28. 8 | */ 9 | 10 | //+a unaryPlus 11 | //-a unaryMinus 12 | //!a not 13 | //++a , a++ inc 14 | //--a , a-- dec 15 | operator fun Point.unaryMinus(): Point { 16 | return Point(-x, -y) 17 | } 18 | 19 | 20 | operator fun Point.unaryPlus(): Point { 21 | return Point(+x, +y) 22 | } 23 | 24 | 25 | operator fun Point.inc(): Point { 26 | return Point(x + 1, y + 1) 27 | } 28 | 29 | operator fun Point.dec(): Point { 30 | return Point(x - 1, y - 1) 31 | } 32 | 33 | operator fun BigDecimal.inc() = this + BigDecimal.ONE 34 | 35 | 36 | fun main(args: Array) { 37 | var p1 = Point(10, 30) 38 | println(+p1) 39 | println(-p1) 40 | println(p1++) 41 | println(++p1) 42 | 43 | var bd = BigDecimal.ZERO 44 | println(bd++) 45 | println(++bd) 46 | } 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/reflection/Book.kt: -------------------------------------------------------------------------------- 1 | package reflection 2 | 3 | import reflection.framework.Dao 4 | import reflection.framework.annotations.Field 5 | import reflection.framework.annotations.ID 6 | import reflection.framework.annotations.Table 7 | 8 | @Table("t_book") 9 | class Book(@ID("id") val id: Int, 10 | @Field("name") val name: String, 11 | @Field("author") var author: String): Dao() { 12 | 13 | private var price = 119.0 14 | 15 | fun present(age: Int) = "book's name = $name, author = $author age = $age" 16 | 17 | companion object { 18 | fun sayHello() { 19 | println("hello") 20 | } 21 | } 22 | 23 | inner class Chapter(private val title: String) { 24 | override fun toString(): String { 25 | return "book_name=$name, chapter_title=$title" 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/reflection/MemberReferenceTest.kt: -------------------------------------------------------------------------------- 1 | package reflection 2 | 3 | import kotlin.reflect.KFunction 4 | import kotlin.reflect.KMutableProperty1 5 | import kotlin.reflect.KProperty1 6 | import kotlin.reflect.full.primaryConstructor 7 | 8 | 9 | fun printProperty(instance: T, prop: KProperty1) { 10 | println("${prop.name} = ${prop.get(instance)}") 11 | } 12 | 13 | fun changeProperty(instance: T, prop: KMutableProperty1) { 14 | val value = prop.get(instance) 15 | prop.set(instance, "$value, Johnny") 16 | } 17 | 18 | fun main() { 19 | 20 | // 1. class references (KClass) 21 | val klazz = Book::class //KClass 22 | println(klazz.isData) 23 | 24 | 25 | val clazz = Book::class.java //Java Class 26 | // 如果无法引用到类名,则可以通过 Java 中 Class.forName 获取 Class,然后转成 KClass 27 | val klass = Class.forName("reflection.Book").kotlin 28 | // 创建实例 29 | var book = klazz.primaryConstructor?.call(1,"Kotlin从入门到放弃", "Chiclaim") as Book 30 | 31 | //var book = Book("Kotlin从入门到放弃", "Chiclaim") 32 | 33 | // 2. bound class references (KClass) 34 | val clz = book::class 35 | 36 | // 3. constructor references (KFunction) 37 | val cr = ::Book 38 | book = cr(1,"Kotlin从入门到放弃", "Chiclaim") 39 | 40 | // 4. bound constructor references 41 | val bcr = book::Chapter //Chapter 是 Book 的内部类,使用外部类的实例创建 bound constructor references 42 | val chapter = bcr("前言") 43 | println(chapter) 44 | 45 | // 5. property references (KProperty) 46 | // 获取属性的值 47 | println(Book::name.get(book)) 48 | // 修改属性的值 49 | Book::author.set(book,"by chiclaim") 50 | 51 | // 6. bound property references (KProperty) 52 | // 获取属性的值 53 | println(book::name.get()) 54 | // 修改属性的值 55 | book::author.set("by kumushuoshuo") 56 | 57 | // 7. function references (KFunction) 58 | val fr = Book::present 59 | println(fr.javaClass) 60 | println("function name is ${fr.name}") 61 | println(fr.invoke(book,12)) 62 | println(fr(book,12)) 63 | 64 | // 8. bound function references (KFunction) 65 | val bfr = book::present 66 | bfr(18) 67 | 68 | } 69 | 70 | 71 | /* 72 | 73 | 74 | Book::name 会生成实现了 KProperty 接口的内部类 75 | 76 | val prop = Book::name 77 | 78 | KProperty1 prop = MemberReferenceTestKt$main$prop$1.INSTANCE; 79 | 80 | final class MemberReferenceTestKt$main$prop$1 extends PropertyReference1 { 81 | public static final KProperty1 INSTANCE = new MemberReferenceTestKt$main$prop$1(); 82 | 83 | public String getName() { 84 | return "name"; 85 | } 86 | 87 | public String getSignature() { 88 | return "getName()Ljava/lang/String;"; 89 | } 90 | 91 | public KDeclarationContainer getOwner() { 92 | return Reflection.getOrCreateKotlinClass(Book.class); 93 | } 94 | 95 | @Nullable 96 | public Object get(@Nullable Object receiver) { 97 | return ((Book)receiver).getName(); 98 | } 99 | } 100 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/reflection/ORM_Test.kt: -------------------------------------------------------------------------------- 1 | package reflection 2 | 3 | import reflection.Book 4 | 5 | /** 6 | * 7 | * @author kumushuoshuo 8 | * @github https://github.com/chiclaim/ 9 | */ 10 | fun main() { 11 | 12 | Book(1,"Kotlin入门到进阶","苦木说说").add() 13 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/reflection/ReflectionBasic.kt: -------------------------------------------------------------------------------- 1 | package reflection 2 | 3 | import kotlin.reflect.full.* 4 | 5 | 6 | fun main() { 7 | val book = Book(1,"Kotin入门到进阶", "kumushuoshuo") 8 | val kClass = book::class 9 | println("simpleName = ${kClass.simpleName}") 10 | println("打印属性--------") 11 | 12 | // 打印成员属性(包括父类中的) 13 | kClass.memberProperties.forEach { 14 | println("memberProperties=${it.name}") 15 | } 16 | // 打印扩展属性(包括父类中的) 17 | kClass.memberExtensionProperties.forEach { 18 | println("memberExtensionProperties=${it.name}") 19 | } 20 | // 打印成员属性(不包括父类中的) 21 | kClass.declaredMemberProperties.forEach { 22 | println("declaredMemberProperties=${it.name}") 23 | } 24 | // 打印扩展属性(不包括父类中的) 25 | kClass.declaredMemberExtensionProperties.forEach { 26 | println("declaredMemberExtensionProperties=${it.name}") 27 | } 28 | 29 | 30 | println("打印函数--------") 31 | 32 | // 打印所有的非扩展函数(包括父类中的) 33 | kClass.memberFunctions.forEach { 34 | println("memberFunctions=${it.name}") 35 | } 36 | // 打印所有的扩展函数(包括父类中的) 37 | kClass.memberExtensionFunctions.forEach { 38 | println("memberExtensionFunctions=${it.name}") 39 | } 40 | // 打印所有的非扩展函数(不包括父类中的) 41 | kClass.declaredMemberFunctions.forEach { 42 | println("declaredMemberFunctions=${it.name}") 43 | } 44 | // 打印所有的扩展函数(不包括父类中的) 45 | kClass.declaredMemberExtensionFunctions.forEach { 46 | println("declaredMemberExtensionFunctions=${it.name}") 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/reflection/framework/Dao.kt: -------------------------------------------------------------------------------- 1 | package reflection.framework 2 | 3 | import higher_order_function.joinToString 4 | import reflection.framework.annotations.Field 5 | import reflection.framework.annotations.ID 6 | import reflection.framework.annotations.Table 7 | import tutorials.lesson10.println 8 | import kotlin.reflect.full.declaredMemberProperties 9 | import kotlin.reflect.full.findAnnotation 10 | import kotlin.reflect.full.hasAnnotation 11 | import kotlin.reflect.jvm.jvmName 12 | 13 | /** 14 | * 15 | * @author kumushuoshuo 16 | * @github https://github.com/chiclaim/ 17 | */ 18 | abstract class Dao : IDao { 19 | override fun add(): Boolean { 20 | // insert into (id,name,author) values(?,?,?) 21 | val klass = javaClass.kotlin 22 | val tableName = klass.findAnnotation()?.name ?: javaClass.simpleName 23 | val map = linkedMapOf().apply { 24 | klass.declaredMemberProperties.filter { 25 | it.annotations.isNotEmpty() 26 | }.forEach { 27 | it.findAnnotation()?.let { propertyAnnotation -> 28 | put(propertyAnnotation.name, it.get(this@Dao)) 29 | return@forEach 30 | } 31 | it.findAnnotation()?.let { propertyAnnotation -> 32 | put(propertyAnnotation.name, it.get(this@Dao)) 33 | return@forEach 34 | } 35 | } 36 | } 37 | val fields = map.keys.joinToString(",") 38 | val values = map.values.joinToString(",") 39 | val sql = "insert into $tableName ($fields) values ($values)" 40 | println(sql) 41 | return true 42 | } 43 | 44 | override fun update(): Boolean { 45 | return false 46 | } 47 | 48 | override fun delete(): Boolean { 49 | return false 50 | } 51 | 52 | override fun select(): List { 53 | return emptyList() 54 | } 55 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/reflection/framework/IDao.kt: -------------------------------------------------------------------------------- 1 | package reflection.framework 2 | 3 | /** 4 | * 5 | * @author kumushuoshuo 6 | * @github https://github.com/chiclaim/ 7 | */ 8 | interface IDao { 9 | fun add(): Boolean 10 | fun update(): Boolean 11 | fun delete(): Boolean 12 | fun select(): List 13 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/reflection/framework/annotations/Field.kt: -------------------------------------------------------------------------------- 1 | package reflection.framework.annotations 2 | 3 | @Target(AnnotationTarget.PROPERTY) 4 | annotation class Field(val name: String) 5 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/reflection/framework/annotations/ID.kt: -------------------------------------------------------------------------------- 1 | package reflection.framework.annotations 2 | 3 | @Target(AnnotationTarget.PROPERTY) 4 | annotation class ID(val name: String) 5 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/reflection/framework/annotations/Table.kt: -------------------------------------------------------------------------------- 1 | package reflection.framework.annotations 2 | 3 | @Target(AnnotationTarget.CLASS) 4 | annotation class Table(val name: String) 5 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/strings/StringUtils.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by dh on 2017/6/26. 3 | */ 4 | 5 | 6 | package strings 7 | 8 | fun String.lastChar(): Char = get(length - 1) 9 | 10 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/test/CompanionTest.kt: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import object_keyword.ObjectKeywordTest 4 | import object_keyword.ObjectKeywordTest2 5 | 6 | /** 7 | * Desc: 访问companion属性、方法 演示 8 | * Created by Chiclaim on 2018/9/20. 9 | */ 10 | fun main(args: Array) { 11 | 12 | println("flag=${ObjectKeywordTest.GENDER}, username=${ObjectKeywordTest.username}") 13 | 14 | 15 | ObjectKeywordTest2.run() 16 | } 17 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/test/InternalClassTest.kt: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import visibility_modifier.modifier_class.InternalClass 4 | 5 | /** 6 | * desc: 调用当前module中internal class 7 | * 8 | * 继承一个internal class 9 | * 10 | * Created by Chiclaim on 2018/09/20 11 | */ 12 | 13 | fun getInternalClassFromThisModule() { 14 | 15 | //InternalClass is a internal class in another package 16 | val p2 = InternalClass() 17 | p2.getName() 18 | 19 | } 20 | 21 | //如果想要继承internal class 首先把internal class设置为open 22 | //还需要把子类也要设置成internal class,为什么要这么做呢? 23 | //因为子类不设置成internal class,那就间接了暴露了原来的internal class了 24 | //这和internal class的设计初衷是相违背的 25 | internal class A : InternalClass() -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/test/JavaDefaultClassTest.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | /** 4 | * Desc: 不同包名无法访问default class 5 | * Created by Chiclaim on 2018/10/18. 6 | */ 7 | public class JavaDefaultClassTest /* extends JavaDefaultClass */ { 8 | } 9 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/test/MemberModifierJavaTest.java: -------------------------------------------------------------------------------- 1 | package test; 2 | 3 | import visibility_modifier.modifier_member.MemberModifierJava; 4 | 5 | /** 6 | * Desc: default只能在同包名下才能访问、protected同包名和子类都可访问 7 | * Created by Chiclaim on 2018/10/18. 8 | */ 9 | public class MemberModifierJavaTest { 10 | 11 | private MemberModifierJava memberModifier = new MemberModifierJava(); 12 | 13 | void call() { 14 | 15 | //无法访问 16 | //memberModifier.asset protected 17 | //memberModifier.username default 18 | //System.out.println(memberModifier.username + " has " + memberModifier.asset); 19 | } 20 | 21 | 22 | } 23 | 24 | class MemberModifierJavaExtends extends MemberModifierJava { 25 | void call() { 26 | //memberModifier.asset protected 子类可以访问 27 | //memberModifier.username default 无法访问 28 | System.out.println("xxx has " + asset); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/test/MemberModifierTest.kt: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import visibility_modifier.modifier_member.MemberModifier 4 | 5 | /** 6 | * Desc: 成员修饰符 演示 7 | * Created by Chiclaim on 2018/9/21. 8 | */ 9 | //在同一个模块,不同包名 10 | class MemberModifierTest { 11 | 12 | val memberModifier: MemberModifier = MemberModifier() 13 | 14 | fun call() { 15 | 16 | //memberModifier.gender internal 17 | //memberModifier.username public 18 | 19 | println("${memberModifier.username}'s gender ${memberModifier.gender}") 20 | } 21 | } 22 | 23 | //继承 24 | class MemberModifierTest2 : MemberModifier() { 25 | fun call() { 26 | //gender //internal 27 | //username //public 28 | //asset //protected 29 | 30 | println("$username's gender $gender, He has $asset") 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson04/JavaSwitchTest.java: -------------------------------------------------------------------------------- 1 | package tutorials.lesson04; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * @author kumushuoshuo 7 | * @github https://github.com/chiclaim/ 8 | */ 9 | public class JavaSwitchTest { 10 | 11 | public static void main(String[] args) { 12 | String value = findValue(); 13 | test(value); 14 | } 15 | 16 | static String findValue() { 17 | if (new Random().nextInt() == 1) { 18 | return ""; 19 | } 20 | return null; 21 | } 22 | 23 | static void test(String value) { 24 | switch (value) { 25 | case "one": 26 | System.out.println("1"); 27 | case "two": 28 | System.out.println("2"); 29 | break; 30 | case "three": 31 | System.out.println(3); 32 | break; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson04/Main.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson04 2 | 3 | /* 4 | * 5 | * @author kumushuoshuo 6 | * @github https://github.com/chiclaim/ 7 | */ 8 | 9 | 10 | fun main() { 11 | testLoop1() 12 | } 13 | 14 | // if 15 | fun testIf(value: Int) { 16 | if (value > 0) { 17 | println(">0") 18 | } else { 19 | println("<=0") 20 | } 21 | } 22 | 23 | // when的基本语法 24 | fun testWhen(value:Int){ 25 | when(value){ 26 | 1->{ 27 | println("1") 28 | } 29 | 2->{ 30 | println("2") 31 | } 32 | } 33 | } 34 | 35 | enum class Color{ 36 | BLUE, 37 | RED, 38 | YELLOW, 39 | ORANGE, 40 | GREEN 41 | } 42 | 43 | // 枚举类对象作为when参数 44 | fun testWhen2(color: Color){ 45 | when(color){ 46 | Color.BLUE ->{ 47 | println("BLUE") 48 | } 49 | Color.RED->{ 50 | println("RED") 51 | } 52 | Color.YELLOW->{ 53 | println("YELLOW") 54 | } 55 | Color.ORANGE->{ 56 | println("ORANGE") 57 | } 58 | Color.GREEN->{ 59 | println("GREEN") 60 | } 61 | } 62 | } 63 | 64 | // 任意对象作为when参数 65 | fun testWhen3(c1: Color, c2: Color) { 66 | when (setOf(c1, c2)) { 67 | 68 | setOf(Color.RED, Color.YELLOW) -> { 69 | Color.ORANGE 70 | } 71 | 72 | setOf(Color.YELLOW, Color.BLUE) -> { 73 | Color.GREEN 74 | } 75 | 76 | //需要处理 其他 情况 77 | else -> throw Exception("Dirty color") 78 | } 79 | } 80 | 81 | // 无参数的when表达式 82 | fun testWhen4(c1: Color, c2: Color) = when { 83 | (c1 == Color.RED && c2 == Color.YELLOW) || (c1 == Color.YELLOW && c2 == Color.RED) -> { 84 | Color.ORANGE 85 | } 86 | (c1 == Color.YELLOW && c2 == Color.BLUE) || (c1 == Color.BLUE && c2 == Color.YELLOW) -> 87 | Color.GREEN 88 | else -> throw Exception("Dirty color") 89 | } 90 | 91 | // 智能类型转换(smart-casts) 92 | fun testCast(value: Any){ 93 | if(value is String){ 94 | println(value.length) 95 | } 96 | 97 | when(value){ 98 | is String->{ 99 | print(value.length) 100 | } 101 | } 102 | } 103 | 104 | fun testWhen5(value:String?){ 105 | when(value){ 106 | "one"->{ 107 | println(1) 108 | } 109 | } 110 | } 111 | 112 | // 循环结构 113 | 114 | fun testLoop1(){ 115 | //while do..while 116 | 117 | 118 | // .. 是一个闭区间 119 | for(i in 0..100){ 120 | print("$i ") 121 | } 122 | 123 | // until 半闭区间 124 | println() 125 | for(i in 0 until 100){ 126 | print("$i ") 127 | } 128 | 129 | // downTo 130 | println() 131 | for(i in 100 downTo 0){ 132 | print("$i ") 133 | } 134 | println() 135 | for(i in 100 downTo 0 step 2){ 136 | print("$i ") 137 | } 138 | 139 | 140 | 141 | 142 | } 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson05/Main.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson05 2 | 3 | /* 4 | * 5 | * @author kumushuoshuo 6 | * @github https://github.com/chiclaim/ 7 | */ 8 | fun main() { 9 | 10 | } 11 | 12 | 13 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson06/Main.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson06 2 | 3 | /* 4 | * 5 | * @author kumushuoshuo 6 | * @github https://github.com/chiclaim/ 7 | */ 8 | 9 | // 访问修饰符 see: visibility_modifier 10 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson07/Main.java: -------------------------------------------------------------------------------- 1 | package tutorials.lesson07; 2 | 3 | 4 | /** 5 | * @author kumushuoshuo 6 | * @github https://github.com/chiclaim/ 7 | */ 8 | public class Main { 9 | 10 | public static void main(String[] args) { 11 | int[] arr = new int[3]; 12 | int[][] arr2 = new int[2][2]; 13 | 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson07/Main.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson07 2 | 3 | /* 4 | * 5 | * @author kumushuoshuo 6 | * @github https://github.com/chiclaim/ 7 | */ 8 | fun main() { 9 | } 10 | 11 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson08/Main.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson08 2 | 3 | /* 4 | * 5 | * @author kumushuoshuo 6 | * @github https://github.com/chiclaim/ 7 | */ 8 | 9 | // @see data_type/NothingTypeTest.kt -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson08/README.md: -------------------------------------------------------------------------------- 1 | # Nothing类型,你不知道的细节 2 | 3 | > @see data_type/NothingTypeTest.kt 4 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson09/Main.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson09 2 | 3 | import java.util.* 4 | 5 | /* 6 | * 7 | * @author kumushuoshuo 8 | * @github https://github.com/chiclaim/ 9 | */ 10 | 11 | // @see: kotlin-in-action/collection 12 | fun main() { 13 | 14 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson10/JavaCompareString.java: -------------------------------------------------------------------------------- 1 | package tutorials.lesson10; 2 | 3 | /** 4 | * @author kumushuoshuo 5 | * @github https://github.com/chiclaim/ 6 | */ 7 | public class JavaCompareString { 8 | public static void main(String[] args) { 9 | //System.out.println("111w".endsWith("W")); 10 | } 11 | 12 | static void test(String str) { 13 | // if (str.equals("YELLOW")) { 14 | // System.out.println("matched!"); 15 | // } 16 | 17 | if ("YELLOW".equals(str)) { 18 | System.out.println("matched!"); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson10/Main.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson10 2 | 3 | import higher_order_function.joinToString 4 | import java.util.* 5 | 6 | fun Any?.log() { 7 | println(this.toString().padStart(50, '-')) 8 | } 9 | 10 | fun Any?.println() { 11 | println(this) 12 | } 13 | 14 | /** 15 | * 16 | * @author kumushuoshuo 17 | * @github https://github.com/chiclaim/ 18 | */ 19 | 20 | private const val NAME = "苦木说说" 21 | 22 | fun main() { 23 | buildString() 24 | compareStr(NAME) 25 | operateString() 26 | testStringCase() 27 | } 28 | 29 | // 构建 string 30 | fun buildString() { 31 | 32 | var str = "Hello " + NAME 33 | 34 | // string interpolation 35 | str = "Hello $NAME" 36 | str = "Hello ${NAME.length}" 37 | 38 | // java StringBuilder 39 | str = buildString { 40 | append("Hello").append(NAME) 41 | } 42 | 43 | // create string from collection 44 | str = NAME.toList().joinToString("-") // 苦-木-说-说 45 | } 46 | 47 | fun compareStr(str: String?) { 48 | 49 | if (str == "YELLOW") { 50 | println("matched!") 51 | } 52 | 53 | if(str.equals("YELLOW",true)){ 54 | println("matched!") 55 | } 56 | 57 | str?.endsWith("xx") 58 | // Java 不支持 endsWith 大小写 59 | str?.endsWith("xx",false) 60 | // Java 不支持 startsWith 大小写 61 | str?.startsWith("xx",true) 62 | } 63 | 64 | fun operateString() { 65 | NAME[0] 66 | NAME.first() // NoSuchElementException 67 | NAME.firstOrNull() 68 | 69 | NAME[NAME.length-1] 70 | NAME.last() // NoSuchElementException 71 | NAME.lastOrNull() 72 | NAME.lastOrNull { 73 | it == '说' 74 | }.println() 75 | 76 | "ifBlank".log() 77 | val blank = " " 78 | blank.ifBlank { "this is a default value" }.println() 79 | blank.ifEmpty { "this is a default value" }.println() 80 | 81 | // 删除前面 n 个字符串 82 | println(NAME.drop(1)) 83 | // 删除后面 n 个字符串 84 | println(NAME.dropLast(1)) 85 | 86 | "removeSurrounding".log() 87 | "##苦木##说说##".removeSurrounding("##").println() 88 | 89 | "split".log() 90 | "苦木.说说".split(".").println() 91 | 92 | 93 | // Pattern.compile("\\w*\\d+\\w*"); 94 | Regex("""\w*\d+\w*""") // raw string 95 | 96 | 97 | "multiline".log() 98 | multiline() 99 | 100 | 101 | // C://ddd/dd/cat.jpg 102 | "get file from path".log() 103 | val fullPath = "/Users/yuzhiqiang/Dev/Workspace/KotlinTutorials/cat.jpg" 104 | fullPath.substring(fullPath.lastIndexOf('/') + 1).println() 105 | fullPath.removeRange(0..fullPath.lastIndexOf('/')).println() 106 | fullPath.substringAfterLast('/').println() 107 | 108 | "removeSuffix".log() 109 | // 获取文件名,不包括后缀 110 | listOf("cat1.jpg", "cat2.jpg", "cat3.jpg").map { 111 | it.removeSuffix(".jpg") 112 | }.forEach(::println) 113 | 114 | // 获取文件名,不包括后缀 115 | "substringBefore".log() 116 | listOf("cat.jpg", "dog.png", "boy.gif").map { 117 | it.substringBefore(".") 118 | }.forEach(::println) 119 | 120 | 121 | } 122 | 123 | fun testStringCase() { 124 | val name = "kumushuoshuo" 125 | println(name.capitalize()) 126 | println(name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }) 127 | 128 | //println(name.toUpperCase()) 129 | println(name.uppercase(Locale.getDefault())) 130 | 131 | //println(name.toLowerCase()) 132 | println(name.lowercase(Locale.getDefault())) 133 | } 134 | 135 | fun multiline() { 136 | println( 137 | """ 138 | Not 139 | trimmed 140 | text 141 | """ 142 | ) 143 | 144 | println( 145 | """ 146 | Trimmed 147 | text 148 | """.trimIndent() 149 | ) 150 | 151 | println() 152 | 153 | val a = """Trimmed to margin text: 154 | |if(a > 1) { 155 | | return a 156 | |}""".trimMargin() 157 | println(a) 158 | 159 | println() 160 | 161 | val a2 = """Trimmed to margin text: 162 | -if(a > 1) { 163 | - return a 164 | -}""".trimMargin("-") 165 | println(a2) 166 | 167 | val a3 = """Trimmed to margin text: 168 | if(a > 1) { 169 | return a 170 | }""" 171 | println(a3) 172 | } 173 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson11/ClassMethod.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson11 2 | 3 | /** 4 | * 5 | * @author kumushuoshuo 6 | * @github https://github.com/chiclaim/ 7 | */ 8 | class ClassMethod { 9 | // 成员函数 10 | fun hello() { 11 | 12 | } 13 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson11/Java.java: -------------------------------------------------------------------------------- 1 | package tutorials.lesson11; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | /** 7 | * @author kumushuoshuo 8 | * @github https://github.com/chiclaim/ 9 | */ 10 | public class Java { 11 | 12 | public static void main(String[] args) { 13 | TopHelper.max(1,2); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson11/Main.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson11 2 | 3 | import base.lastChar 4 | import tutorials.lesson10.println 5 | 6 | /* 7 | * 8 | * @author kumushuoshuo 9 | * @github https://github.com/chiclaim/ 10 | */ 11 | 12 | fun main() { 13 | printNames("kmss") 14 | // 调用函数时给定参数名 15 | printNames("kmss", penName = "shuo") 16 | 17 | "kmss".lastChar() 18 | 19 | multiple().println() 20 | 21 | 22 | 23 | } 24 | 25 | // 函数参数默认值 26 | fun printNames(realName: String, nickName: String = "苦木说说", penName: String = "kumushuoshuo") { 27 | println("realName=$realName,nickName=$nickName,penName=$penName") 28 | } 29 | 30 | // 单表达式函数 31 | fun add(num1: Int, num2: Int) = num1 + num2 32 | fun min(num1: Int, num2: Int) = if (num1 < num2) num1 else num2 33 | 34 | 35 | // 可变参数 36 | fun multiple(vararg nums: Int): Int { 37 | if (nums.isEmpty()) return 0 38 | return nums.fold(1) { acc, it -> 39 | acc * it 40 | } 41 | } 42 | 43 | fun testAnonymousFun(){ 44 | // 匿名函数 45 | (fun(x: Int, y: Int): Int { 46 | val result = x + y 47 | println("sum:$result") 48 | return result 49 | })(1, 9) 50 | } 51 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson11/Top.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("TopHelper") 2 | package tutorials.lesson11 3 | 4 | /* 5 | * 6 | * @author kumushuoshuo 7 | * @github https://github.com/chiclaim/ 8 | */ 9 | 10 | // 顶级函数(类的外部) 11 | fun max(num1: Int, num2: Int): Int { 12 | return if (num1 > num2) num1 else num2 13 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson12/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | > see kotlin-in-action/new_class 4 | 5 | - create class 6 | - primary constructor、secondary constructor 7 | - companion object 8 | - object class 9 | - object keyword summary 10 | - init block 11 | - inner class 12 | - sealed class 13 | - data class 14 | - interface -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson13/Introspection.java: -------------------------------------------------------------------------------- 1 | package tutorials.lesson13; 2 | 3 | import java.beans.BeanInfo; 4 | import java.beans.IntrospectionException; 5 | import java.beans.Introspector; 6 | import java.beans.PropertyDescriptor; 7 | import java.lang.reflect.Method; 8 | 9 | /** 10 | * @author kumushuoshuo 11 | * @github https://github.com/chiclaim/ 12 | */ 13 | public class Introspection { 14 | public static void main(String[] args) throws IntrospectionException { 15 | BeanInfo beanInfo = Introspector.getBeanInfo(PF.class); 16 | 17 | PropertyDescriptor[] proDescriptors = beanInfo.getPropertyDescriptors(); 18 | for (PropertyDescriptor prop : proDescriptors) { 19 | System.out.println("pro name : "+prop.getName()); 20 | } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson13/PF.java: -------------------------------------------------------------------------------- 1 | package tutorials.lesson13; 2 | 3 | /** 4 | * @author kumushuoshuo 5 | * @github https://github.com/chiclaim/ 6 | */ 7 | public class PF { 8 | 9 | private String st = "PF"; 10 | private static String str = "PF"; 11 | private static final String STR = "PF"; 12 | 13 | private boolean isOk; 14 | 15 | public void setName(String name) { 16 | } 17 | 18 | public String getName() { 19 | return ""; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson14/LateinitTest.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson14 2 | 3 | class LateinitTest{ 4 | lateinit var name:String 5 | 6 | fun checkInit(){ 7 | println(::name.isInitialized) 8 | name = "kumushuoshuo" 9 | println(::name.isInitialized) 10 | } 11 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson14/Main.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson14 2 | 3 | import base.Person 4 | 5 | /* 6 | * 7 | * @author kumushuoshuo 8 | * @github https://github.com/chiclaim/ 9 | */ 10 | 11 | const val DD = "ddd" 12 | const val COUNT = 100 13 | 14 | val dd:Person = Person("kumushuoshuo") 15 | 16 | 17 | fun main() { 18 | val propertyTest = PropertyTest() 19 | //propertyTest.name 20 | propertyTest.name = "kumushuoshuo" 21 | 22 | propertyTest.setGender(1) 23 | 24 | //val test = LateinitTest() 25 | //test.checkInit() 26 | } 27 | 28 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson14/PropertyTest.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson14 2 | 3 | /** 4 | * 5 | * @author kumushuoshuo 6 | * @github https://github.com/chiclaim/ 7 | */ 8 | class PropertyTest { 9 | 10 | var name:String? = "苦木说说" 11 | get() { 12 | println("invoke get()") 13 | return field 14 | } 15 | set(value) { 16 | println("invoke set()") 17 | field = value 18 | } 19 | 20 | var salary = 0 21 | private set 22 | 23 | var age = 0 24 | // https://youtrack.jetbrains.com/issue/KT-3110 25 | // private get //error 26 | 27 | private var gender = 1 28 | fun setGender(sex:Int){ 29 | gender = sex 30 | } 31 | 32 | var isEmpty: Boolean = true 33 | private set 34 | get(){ 35 | field = false 36 | return false 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson14/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - property 4 | - backing field 5 | - backing property 6 | - const property 7 | - lateinit property 8 | - isInitialized 9 | - [delegated properties] -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson14/TEST.java: -------------------------------------------------------------------------------- 1 | package tutorials.lesson14; 2 | 3 | import base.Person; 4 | 5 | /** 6 | * @author kumushuoshuo 7 | * @github https://github.com/chiclaim/ 8 | */ 9 | public class TEST { 10 | private static final Person PERSON = new Person("kumushuoshuo"); 11 | } 12 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson15/REAMD.md: -------------------------------------------------------------------------------- 1 | 2 | > kotlin-in-action/delegated 3 | 4 | # 属性委托 5 | 6 | - 主要内容: 7 | - by 8 | - by lazy 9 | - by Delegates.observable 10 | 11 | 12 | - by 使用、原理 13 | - 属性字节码生成机制 14 | - by 使用、原理 15 | - Lazy 机制 16 | - 实现类似的机制,需要注意的事项 17 | - Lazy 分析 18 | 19 | - by Delegates.observable 20 | - 手动实现 21 | - 原理分析 22 | 23 | 1. 再次深入理解Kotlin属性 字节码生成机制: 24 | 1. 不要机械的认为 val 修饰的属性,就会生一个 field 和 getter 方法 25 | 2. 不要机械的认为 var 修饰的属性,就会生成一个 field 和对应的 getter 和 setter 方法 26 | 3. 是否生成 field 取决于该属性是否存在 backing field 27 | 28 | 29 | 2. 扩展函数的坑 30 | 1. 使用方便 31 | 2. 有时候会增加代码理解困难 调用 getXXX(), Kotlin 直接使用 xxx 的方法 32 | 33 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson16/README.md: -------------------------------------------------------------------------------- 1 | 2 | 属性委托(二) 3 | 4 | - lazy mode 5 | - LazyThreadSafetyMode.SYNCHRONIZED 6 | - LazyThreadSafetyMode.PUBLICATION 7 | 8 | > kotlin-in-action/delegated -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson17/README.md: -------------------------------------------------------------------------------- 1 | 2 | 属性委托(三) 3 | - by map 4 | - by map 字节码反编译分析 5 | - by map 和普通的 by delegation 的区别 6 | - 委托模式 7 | - Kotlin 委托模式字节码反编译分析 8 | - Kotlin 如何简化委托模式 9 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson18/Main.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson18 2 | 3 | /* 4 | * 5 | * @author kumushuoshuo 6 | * @github https://github.com/chiclaim/ 7 | */ 8 | 9 | enum class Country { 10 | CN, 11 | USA 12 | } 13 | 14 | fun printCountryWithEnum(country: Country) { 15 | when (country) { 16 | Country.CN -> println("中国") 17 | Country.USA -> println("美国") 18 | } 19 | } 20 | 21 | fun main() { 22 | printCountryWithEnum(Country.CN) 23 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson18/README.md: -------------------------------------------------------------------------------- 1 | 2 | Enum 3 | 4 | - 为什么要有枚举 5 | - 枚举 API 特性 6 | - 枚举的本质 7 | - 枚举是如何判断相等的 8 | - 枚举最佳实践 -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson18/WithoutEnum.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson18 2 | 3 | /** 4 | * 5 | * @author kumushuoshuo 6 | * @github https://github.com/chiclaim/ 7 | */ 8 | const val CN = 1 9 | const val USA = 2 10 | 11 | fun printCountryWithInt(country: Int) { 12 | when (country) { 13 | CN -> println("中国") 14 | USA -> println("美国") 15 | } 16 | } 17 | 18 | fun main() { 19 | printCountryWithInt(CN) 20 | printCountryWithInt(99) 21 | 22 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson18/WithoutEnum2.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson18 2 | 3 | /** 4 | * 5 | * @author kumushuoshuo 6 | * @github https://github.com/chiclaim/ 7 | */ 8 | class Country2 private constructor() { 9 | 10 | companion object { 11 | val CN = Country2() 12 | val USA = Country2() 13 | } 14 | 15 | } 16 | 17 | fun printCountryWithClass(country: Country2) { 18 | when (country) { 19 | Country2.CN -> println("中国") 20 | Country2.USA -> println("美国") 21 | } 22 | } 23 | 24 | fun main() { 25 | printCountryWithClass(Country2.CN) 26 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson23/Main.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson23 2 | 3 | import tutorials.lesson23.PosTypeEnum.* 4 | 5 | /** 6 | * Kotlin 1.6 when 在使用 枚举、Sealed class 的变化 7 | * 8 | * 9 | * @author kumushuoshuo 10 | * @github https://github.com/chiclaim/ 11 | */ 12 | 13 | sealed class PosType private constructor(){ 14 | object ABC : PosType() 15 | class ICBC : PosType() 16 | } 17 | 18 | // 如果 sealed class 的子类不需要保存数据,或者数据是没有状态的,则可以使用单例,此时和枚举非常像 19 | /* 20 | sealed class PosType { 21 | object ABC : PosType() 22 | object ICBC : PosType() 23 | } 24 | */ 25 | 26 | fun testWhenExpressionSealedClass(posType: PosType) { 27 | val value:Int = when (posType) { 28 | is PosType.ABC -> 1 29 | is PosType.ICBC -> 2 30 | } 31 | println(value) 32 | } 33 | 34 | //fun testWhenStatementSealedClass(posType: PosType) { 35 | // // 编译报错:'when' expression must be exhaustive, add necessary 'is ICBC' branch or 'else' branch instead 36 | // when (posType) { 37 | // is PosType.ABC -> 1 // kotlin 1.7 会编译报错 38 | // 39 | // } 40 | //} 41 | 42 | 43 | enum class PosTypeEnum { 44 | ABC, ICBC 45 | } 46 | 47 | fun testWhenExpressionEnum(posType: PosTypeEnum) { 48 | val value = when (posType) { 49 | ABC -> 1 50 | ICBC -> 2 51 | } 52 | } 53 | 54 | //fun testWhenStatementEnum(b: PosTypeEnum) { 55 | // // 编译报错:'when' expression must be exhaustive, add necessary 'is ICBC' branch or 'else' branch instead 56 | // // kotlin 1.7 会编译报错 57 | // when (b) { 58 | // ABC -> 1 59 | // } 60 | //} 61 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson23/NonSealedClass.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson23 2 | 3 | 4 | abstract class Gender { 5 | class Male : Gender() 6 | class Female : Gender() 7 | } 8 | 9 | class DoubleSex : Gender() 10 | 11 | fun testWhenClass(gender: Gender) { 12 | when (gender) { 13 | is Gender.Male -> println("Male") 14 | is Gender.Female -> println("Female") 15 | 16 | } 17 | } 18 | 19 | /* 20 | 如果我们打成 jar 给其他地方使用,如果外部继承了 Gender,然后将新的类型传递给 testWhenClass2, 21 | 那么我们封装的类就会有问题,因为一开始我们以为只会有 Male、Female 22 | */ 23 | fun testWhenClass2(gender: Gender) { 24 | when (gender) { 25 | is Gender.Male -> println("Male") 26 | else -> println("Female") 27 | } 28 | } 29 | 30 | fun main() { 31 | testWhenClass(Gender.Male()) 32 | } 33 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson23/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1. kotlin 1.6 when 对于 sealed class、enum、bool 的穷举 4 | 2. sealed class 可见性只有两个 private 和 protected,默认为 protected,如果为 private 只能通过内部类的方式声明子类,如果为 protected 可以在同包名下声明子类 5 | 3. 如果需要限定 sealed class 的子类只能在父类中定义,可以将构造方法声明为私有,private constructor,否则sealed class 的子类可以在当前包名下任意位置新建子类 6 | 4. sealed interface 无法设置私有构造方法,因为接口没有构造方法 7 | 5. sealed class 和普通类的区别在于 8 | 1. sealed class 在结合 when 使用时具有'穷尽'特性,普通类则没有 9 | 2. sealed class 在编译期就能确定所有的直接子类 10 | 6. 枚举是一组单例对象,而 sealed class 是一组 class,可以创建多个实例,如果对象不需要持有数据或者数据是不变的,可以使用枚举;如果需要创建对象,且对象的数据是变化的,可以使用 sealed class 11 | 12 | 13 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson25/Main.java: -------------------------------------------------------------------------------- 1 | package tutorials.lesson25; 2 | 3 | import java.io.*; 4 | import java.nio.file.Files; 5 | 6 | /** 7 | * @author kumushuoshuo 8 | * @github https://github.com/chiclaim/ 9 | */ 10 | public class Main { 11 | 12 | private void printFile() { 13 | BufferedReader br = null; 14 | try { 15 | br = new BufferedReader(new FileReader("test.txt")); 16 | String line; 17 | while ((line = br.readLine()) != null) { 18 | System.out.println(line); 19 | } 20 | } catch (IOException e) { 21 | e.printStackTrace(); 22 | } finally { 23 | if (br != null) { 24 | try { 25 | br.close(); 26 | } catch (IOException e) { 27 | e.printStackTrace(); 28 | } 29 | } 30 | } 31 | } 32 | 33 | private void printFile2() { 34 | // try-with-resource 35 | try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) { 36 | String line; 37 | while ((line = br.readLine()) != null) { 38 | System.out.println(line); 39 | } 40 | } catch (IOException e) { 41 | e.printStackTrace(); 42 | } 43 | } 44 | 45 | private void copy() { 46 | InputStream is = null; 47 | OutputStream os = null; 48 | try { 49 | is = new FileInputStream("D:\\imagetest\\desk.jpg"); 50 | os = new FileOutputStream("E:\\desk1.jpg"); 51 | byte[] buffer = new byte[1024]; 52 | int readNum = 0; 53 | int a = 0; 54 | while ((readNum = is.read(buffer, 0, buffer.length)) != -1) { 55 | System.out.println(a++); 56 | os.write(buffer, 0, readNum); 57 | } 58 | } catch (IOException e) { 59 | e.printStackTrace(); 60 | } finally { 61 | if (os != null) { 62 | try { 63 | os.close(); 64 | } catch (IOException e) { 65 | e.printStackTrace(); 66 | } 67 | } 68 | if (is != null) { 69 | try { 70 | is.close(); 71 | } catch (IOException e) { 72 | e.printStackTrace(); 73 | } 74 | } 75 | } 76 | } 77 | 78 | 79 | } 80 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson25/Main.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson25 2 | 3 | import java.io.File 4 | 5 | /** 6 | * 7 | * @author kumushuoshuo 8 | * @github https://github.com/chiclaim/ 9 | */ 10 | 11 | 12 | val file = File("kotlin-in-action/src/tutorials/lesson25/file.txt") 13 | 14 | fun testWrite() { 15 | file.writeBytes("kumushuoshuo writeBytes\n".toByteArray()) 16 | //file.writeText("kumushuoshuo writeText\n") 17 | file.appendBytes("kumushuoshuo appendBytes\n".toByteArray()) 18 | file.appendText("kumushuoshuo appendText\n") 19 | // file.outputStream().use { 20 | // it.write("kumushuoshuo outputStream\n".toByteArray()) 21 | // } 22 | // file.printWriter().use { 23 | // it.println("kumushuoshuo printWriter") 24 | // } 25 | // file.bufferedWriter().use { 26 | // it.write("kumushuoshuo") 27 | // } 28 | 29 | } 30 | 31 | fun testRead() { 32 | println("forEachLine-------------------->") 33 | file.forEachLine{ 34 | println(it) 35 | } 36 | println("forEachBlock-------------------->") 37 | file.forEachBlock { buffer: ByteArray, _: Int -> 38 | print(buffer.decodeToString()) 39 | } 40 | println("inputStream-------------------->") 41 | file.inputStream().use { 42 | var value: Int = it.read() 43 | while (value != -1) { 44 | print(value.toChar()) 45 | value = it.read() 46 | } 47 | } 48 | println("inputStream buffer-------------------->") 49 | file.inputStream().use { 50 | val byteArray = ByteArray(1024) 51 | var value: Int = it.read(byteArray,0,byteArray.size) 52 | while (value != -1) { 53 | print(byteArray.decodeToString()) 54 | value = it.read(byteArray,0,byteArray.size) 55 | } 56 | } 57 | println("bufferedReader-------------------->") 58 | file.bufferedReader().use { 59 | it.readLines().forEach(::println) 60 | } 61 | 62 | 63 | } 64 | 65 | fun testOther(){ 66 | // 文件后缀 67 | println(file.extension) 68 | 69 | // 文件名 70 | println(file.nameWithoutExtension) 71 | 72 | // 遍历文件夹 73 | file.parentFile.parentFile 74 | //.walk()// 先访问文件夹,再访问它文件夹里的内容 75 | .walkBottomUp()// 先访问文件,再访问它文件夹 76 | .maxDepth(2) // 访问深度 77 | //.filter {it.extension.equals("txt",true) } 78 | .forEach(::println) 79 | 80 | // 文件拷贝 81 | file.copyTo(File(file.parent,"copy.txt"), overwrite = true) 82 | 83 | // 文件夹拷贝 84 | file.parentFile.copyRecursively(File(file.parentFile.parentFile.parentFile.parent,"copyRecursively"),true) 85 | } 86 | 87 | 88 | fun main() { 89 | //testWrite() 90 | //testRead() 91 | testOther() 92 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson25/README.md: -------------------------------------------------------------------------------- 1 | 2 | > https://github.com/chiclaim/KotlinTutorials 3 | 4 | # Kotlin 文件 IO 操作 5 | 6 | ## 写文件 7 | 8 | - writeBytes 9 | - writeText 10 | - appendBytes 11 | - appendText 12 | - outputStream 13 | - bufferedWriter 14 | 15 | 16 | ## 读文件 17 | 18 | - forEachLine 19 | - forEachBlock 20 | - inputStream 21 | - bufferedReader 22 | 23 | # 拷贝 24 | 25 | - copyTo 26 | - copyRecursively 27 | 28 | # 遍历 29 | 30 | - walk 31 | - walkBottomUp 32 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson25/file.txt: -------------------------------------------------------------------------------- 1 | kumushuoshuo writeBytes 2 | kumushuoshuo appendBytes 3 | kumushuoshuo appendText 4 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson26/JavaException.java: -------------------------------------------------------------------------------- 1 | package tutorials.lesson26; 2 | 3 | /** 4 | * @author kumushuoshuo 5 | * @github https://github.com/chiclaim/ 6 | */ 7 | public class JavaException { 8 | 9 | //unchecked exception 包括 RuntimeException, Error, 和他们的子类 10 | 11 | // checked exception 12 | static void testCheckedException() throws Throwable{ 13 | 14 | } 15 | 16 | // unchecked exception 17 | static void testUnCheckedException() throws NullPointerException{ 18 | 19 | } 20 | 21 | // unchecked exception 22 | static void testError() throws StackOverflowError{ 23 | testError(); 24 | // do something ... 25 | } 26 | 27 | 28 | public static void main(String[] args) { 29 | try { 30 | testCheckedException(); 31 | } catch (Throwable e) { 32 | throw new RuntimeException(e); 33 | } 34 | 35 | testUnCheckedException(); 36 | 37 | // 不要对 error 进行 try catch 38 | try { 39 | testError(); 40 | } catch (StackOverflowError e) { 41 | 42 | } 43 | System.out.println("after error"); 44 | 45 | 46 | 47 | } 48 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson26/KtException.kt: -------------------------------------------------------------------------------- 1 | @file:JvmName("KtException") 2 | 3 | package tutorials.lesson26 4 | 5 | import java.io.FileNotFoundException 6 | import java.io.IOException 7 | 8 | /* 9 | * 10 | * @author kumushuoshuo 11 | * @github https://github.com/chiclaim/KotlinTutorials 12 | */ 13 | 14 | fun readFile(path: String) { 15 | throw FileNotFoundException("") 16 | } 17 | 18 | // 给 Java 调用,如果希望调用 try...catch,可以使用 @Throws 注解 19 | // kotlin 没有 throws 关键字,只有 throw 关键字 20 | @kotlin.jvm.Throws(IOException::class) 21 | fun readFile2(path: String) { 22 | 23 | } 24 | 25 | fun main() { 26 | readFile("file") 27 | 28 | 29 | // try 是一个表达式 30 | val num = try { 31 | "".toInt() 32 | } catch (e: NumberFormatException) { 33 | -1 34 | } 35 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson26/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Kotlin 异常(一) 3 | 4 | - Java 异常 5 | - Java 异常体系 6 | - checked exception 7 | - unchecked exception 8 | 9 | - Kotlin 异常 10 | - Kotlin Java 异常的区别 11 | - Kotlin 异常是一个表达式 12 | - Kotlin 没有 checked exception -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson27/JavaAbusedCheckedException.java: -------------------------------------------------------------------------------- 1 | package tutorials.lesson27; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.FileNotFoundException; 6 | import java.io.IOException; 7 | import java.security.InvalidAlgorithmParameterException; 8 | import java.security.MessageDigest; 9 | import java.security.NoSuchAlgorithmException; 10 | 11 | /** 12 | * 滥用 Checked Exception 13 | * 14 | * @author kumushuoshuo 15 | * @github https://github.com/chiclaim/ 16 | */ 17 | public class JavaAbusedCheckedException { 18 | 19 | // 抛出长长的异常列表 20 | void case1() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, 21 | FileNotFoundException, ClassNotFoundException { 22 | ThrowsTest.test1(); 23 | ThrowsTest.test2(); 24 | ThrowsTest.test3(); 25 | ThrowsTest.test4(); 26 | } 27 | 28 | // 为了避免长长的异常列表,可能会这样做: 29 | void case2() throws Throwable { 30 | ThrowsTest.test1(); 31 | ThrowsTest.test2(); 32 | ThrowsTest.test3(); 33 | ThrowsTest.test4(); 34 | } 35 | 36 | // 如果不对外抛出异常,可能会直接 try...catch 异常,避免 37 | void case3() { 38 | try { 39 | ThrowsTest.test1(); 40 | ThrowsTest.test2(); 41 | ThrowsTest.test3(); 42 | ThrowsTest.test4(); 43 | } catch (Throwable t) { 44 | t.printStackTrace(); 45 | } 46 | } 47 | 48 | // 我们知道不会抛出异常,但是也不得不 try...catch 49 | // ByteArrayInputStream 50 | void test4() { 51 | try { 52 | MessageDigest md = MessageDigest.getInstance("MD5"); 53 | } catch (NoSuchAlgorithmException e) { 54 | e.printStackTrace(); 55 | } 56 | } 57 | 58 | 59 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson27/KtDesignExceptionApi.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson27 2 | 3 | /** 4 | * 5 | * @author kumushuoshuo 6 | * @github https://github.com/chiclaim/ 7 | */ 8 | fun watchTry(type: String) { 9 | var orderType: Int? = -1 10 | try { 11 | orderType = type.toInt() 12 | } catch (e: NumberFormatException) { 13 | e.printStackTrace() 14 | orderType = null 15 | } 16 | if (orderType != null) { 17 | // todo something 18 | } 19 | } 20 | 21 | fun watchTry2(type: String) { 22 | // 将低层次异常进行封装,避免模板代码 23 | val orderType = type.toIntOrNull() 24 | if (orderType != null) { 25 | // todo something 26 | } 27 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson27/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Kotlin 异常(二) 3 | 4 | > Kotlin异常设计理念、异常API设计 5 | 6 | https://elizarov.medium.com/kotlin-and-exceptions-8062f589d07 7 | 8 | https://discuss.kotlinlang.org/t/in-future-could-kotlin-have-checked-exceptions/1579 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson27/ThrowsTest.java: -------------------------------------------------------------------------------- 1 | package tutorials.lesson27; 2 | 3 | import java.io.FileNotFoundException; 4 | import java.security.InvalidAlgorithmParameterException; 5 | import java.security.NoSuchAlgorithmException; 6 | 7 | /** 8 | * @author kumushuoshuo 9 | * @github https://github.com/chiclaim/ 10 | */ 11 | public class ThrowsTest{ 12 | 13 | public static void test1() throws NoSuchAlgorithmException { 14 | 15 | } 16 | 17 | public static void test2() throws InvalidAlgorithmParameterException { 18 | 19 | } 20 | 21 | public static void test3() throws FileNotFoundException { 22 | 23 | } 24 | 25 | public static void test4() throws ClassNotFoundException { 26 | 27 | } 28 | 29 | 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson27/UncaughtExceptionHandlerTest.java: -------------------------------------------------------------------------------- 1 | package tutorials.lesson27; 2 | 3 | /** 4 | * @author kumushuoshuo 5 | * @github https://github.com/chiclaim/ 6 | */ 7 | public class UncaughtExceptionHandlerTest { 8 | 9 | 10 | public static void main(String[] args) throws InterruptedException { 11 | Thread.setDefaultUncaughtExceptionHandler((t, e) -> { 12 | // 全局处理异常 13 | System.out.println("哦吼,发生异常了:"+e.getMessage()); 14 | }); 15 | 16 | while (true){ 17 | Thread.sleep(1000); 18 | new Thread(){ 19 | @Override 20 | public void run() { 21 | super.run(); 22 | throw new NullPointerException("NPE"); 23 | } 24 | }.start(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson28/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # Kotlin 注解 5 | 6 | - 注解的定义 7 | - Kotlin 元注解 8 | - @Target 9 | - @Retention 10 | - @Repeatable 11 | - @MustBeDocumented 12 | - use-site target 13 | - @file the class containing top-level functions and properties declared in the file 14 | - @property: annotations with this target are not visible to Java 15 | - @field: the field generated for the property 16 | - @get: property getter 17 | - @set: property setter 18 | - @receiver: receiver parameter of an extension function or property 19 | - @param: constructor parameter 20 | - @setparam: property setter parameter 21 | - @delegate: the field storing the delegate instance for a delegated property -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson29/Main.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson29 2 | 3 | /** 4 | * 5 | * @author kumushuoshuo 6 | * @github https://github.com/chiclaim/ 7 | */ 8 | 9 | // see kotlin-in-action/reflection 10 | fun main() { 11 | 12 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson29/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 深入理解 Kotlin 反射 4 | 5 | ## 反射 API 6 | - KClass 7 | - KCallable 8 | - KFunction 9 | - KProperty 10 | 11 | ## member references 12 | 13 | class references 14 | bound class references 15 | 16 | constructor references 17 | bound constructor references 18 | 19 | property references 20 | bound property references 21 | 22 | function references 23 | bound function references 24 | 25 | ## member references 原理分析 26 | 27 | 28 | > kotlin.Function 类用于描述 functional type 的值, 如 function references、lambda、匿名函数 29 | 30 | - functional type 31 | - function references 32 | - lambda 33 | - 匿名函数 -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson30/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 深入理解 lambda 表达式 4 | 5 | 6 | - lambda 语法 7 | - lambda 与集合(引出 member references) 8 | - lambda 与 member references 9 | - lambda 与 Java functional interface(SAM) 10 | - functional type(高阶函数) 11 | - lambda 与 receiver 12 | - lambda 原理分析 13 | 14 | ----- 15 | 16 | - functional interface 17 | - functional type 18 | 19 | > kotlin.Function 类用于描述 functional type 的值, 如 function references、lambda、匿名函数 20 | 21 | - functional type 22 | - function references 23 | - lambda 24 | - 匿名函数 -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson31/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 深入理解高阶函数 4 | 5 | 6 | - 什么是高阶函数 7 | - 高阶函数语法 8 | - 再谈 function type 9 | - function type 语法 10 | - function type 参数命名 11 | - 可空的 function type 12 | - function type 作为参数 13 | - function type 作为返回值 14 | - function type 与 lambda receiver 15 | - 记住:谁调用 function type 谁就是 receiver 16 | - scope-functions 17 | - let 18 | - with 19 | - run 20 | - apply 21 | - also 22 | - 原理分析 23 | 24 | 25 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson32/Main.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson32 2 | 3 | // inline/noinline/crossinline 4 | class Main { 5 | 6 | var age = 10 7 | 8 | inline fun inlineFun() { 9 | println("from inlineFun") 10 | } 11 | 12 | 13 | private inline fun proxy(action: () -> Unit) { 14 | println("start logging") 15 | action() 16 | println("end logging") 17 | } 18 | 19 | fun invokeProxy() { 20 | proxy { 21 | age = 18 22 | println("eating") 23 | } 24 | } 25 | 26 | private inline fun normalProxy(action: () -> Unit) { 27 | println("start logging") 28 | action() 29 | println("end logging") 30 | } 31 | 32 | fun test(age:Int) { 33 | if (age <= 0) { 34 | return 35 | } 36 | println(age) 37 | } 38 | 39 | fun invokeProxy2() { 40 | normalProxy { 41 | if(age<=0){ 42 | return 43 | } 44 | println(age) 45 | } 46 | } 47 | 48 | // Non-local returns 49 | 50 | // noinline 51 | 52 | private fun cleanResource(execution: () -> Unit) { 53 | execution() 54 | println("cleaning resource1") 55 | println("cleaning resource2") 56 | } 57 | 58 | private inline fun proxy(action: () -> Unit, noinline action2: () -> Unit) { 59 | println("start logging") 60 | action() 61 | println("end logging") 62 | cleanResource(action2) 63 | } 64 | 65 | fun invokeProxy3() { 66 | proxy({ 67 | println("eating...") 68 | }, { 69 | println("eating...2") 70 | }) 71 | } 72 | 73 | // crossinline 74 | 75 | private fun wrap(action: () -> Unit) { 76 | action.invoke() 77 | } 78 | 79 | private inline fun proxy2(noinline action: () -> Unit) { 80 | println("start logging") 81 | wrap { 82 | action() 83 | } 84 | println("end logging") 85 | } 86 | 87 | 88 | private fun invoke(){ 89 | proxy2{ 90 | println("-----") 91 | } 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/tutorials/lesson33/Main.kt: -------------------------------------------------------------------------------- 1 | package tutorials.lesson33 2 | 3 | 4 | fun testForContinue() { 5 | for (i in 1..10) { 6 | if (i % 2 == 0) continue 7 | println(i) 8 | } 9 | println("end...") 10 | } 11 | 12 | fun testForBreak() { 13 | for (i in 1..10) { 14 | if (i % 2 == 0) break 15 | println(i) 16 | } 17 | println("end...") 18 | } 19 | 20 | fun testNestForBreak() { 21 | loop@ for (i in 1..10) { 22 | for (j in 1..10) { 23 | if (i % 2 == 0) break@loop 24 | } 25 | println(i) 26 | } 27 | println("end...") 28 | } 29 | 30 | fun testForReturn() { 31 | for (i in 1..10) { 32 | if (i % 2 == 0) return 33 | println(i) 34 | } 35 | println("end...") 36 | } 37 | 38 | fun testForeachReturn() { 39 | val list = arrayListOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 40 | list.forEach { i -> 41 | if (i % 2 == 0) return 42 | println(i) 43 | } 44 | println("end...") 45 | } 46 | 47 | fun testForeachContinue() { 48 | val list = arrayListOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 49 | list.forEach { i -> 50 | // if (i % 2 == 0) continue 51 | if (i % 2 == 0) return@forEach 52 | println(i) 53 | } 54 | println("end...") 55 | } 56 | 57 | 58 | fun testForeachBreak() { 59 | val list = arrayListOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 60 | run loop@{ 61 | list.forEach { i -> 62 | // if (i % 2 == 0) break 63 | if (i % 2 == 0) return@loop 64 | println(i) 65 | } 66 | } 67 | println("end...") 68 | 69 | } 70 | 71 | private inline fun normalFunction(action: () -> Unit) { 72 | action() 73 | } 74 | 75 | fun invokeNormalFunction() { 76 | var age = 0 77 | // 调用高阶函数 78 | normalFunction { 79 | if (age <= 0) return 80 | println("age:$age") 81 | } 82 | println("end!!!") 83 | } 84 | 85 | fun invoke2NormalFunction() { 86 | var age = 0 87 | // 调用高阶函数 88 | normalFunction { 89 | if (age <= 0) return@normalFunction 90 | println("age:$age") 91 | } 92 | println("end!!!") 93 | } 94 | 95 | fun invoke3NormalFunction() { 96 | var age = 0 97 | // 调用高阶函数 98 | normalFunction loop@{ // 自定义 label 名字 99 | if (age <= 0) return@loop // local return 100 | println("age:$age") 101 | } 102 | println("end!!!") 103 | } 104 | 105 | fun main() { 106 | invoke2NormalFunction() 107 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/visibility_modifier/README.md: -------------------------------------------------------------------------------- 1 | 2 | #### Kotlin和Java protected class 的区别 3 | 4 | Java只能在同包名下可以继承 protected class 5 | Java可以访问同包名下的 protected class 6 | 7 | Kotlin就算同包名下也不能访问 protected class 8 | Kotlin就算同包名下也不能继承 protected class 9 | 10 | 既然Kotlin不能访问和继承同包名下的 protected class,那么 protected class 不就和 private class 一样了吗? 11 | 在Kotlin中要是使用 protected class ,需要继承 protected class的外部类,然后我们就可以使用 它里面的 protected class了 12 | 如果外部类不能被继承,那里面的 protected class 和 private class 没有区别,在这种情况下,编译器也建议我们把 protected 改成 private 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/visibility_modifier/modifier_class/InternalClass.kt: -------------------------------------------------------------------------------- 1 | package visibility_modifier.modifier_class 2 | 3 | /** 4 | * desc: internal修饰的class只在当前module可见 5 | * 6 | * Created by Chiclaim on 2018/09/20 7 | */ 8 | 9 | internal open class InternalClass { 10 | fun getName(): String { 11 | return "chiclaim" 12 | } 13 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/visibility_modifier/modifier_class/PrivateClass.kt: -------------------------------------------------------------------------------- 1 | package visibility_modifier.modifier_class 2 | 3 | /** 4 | * Desc: private class 只在当前文件可访问 5 | * Created by Chiclaim on 2018/9/21. 6 | */ 7 | private class PrivateClass -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/visibility_modifier/modifier_class/PublicClass.kt: -------------------------------------------------------------------------------- 1 | package visibility_modifier.modifier_class 2 | 3 | /** 4 | * Desc: 默认为 public final 5 | * Created by Chiclaim on 2018/9/21. 6 | */ 7 | class PublicClass 8 | 9 | /* 10 | 11 | public final class PublicClass { 12 | } 13 | 14 | */ -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/visibility_modifier/modifier_class/default_/JavaDefaultClass.java: -------------------------------------------------------------------------------- 1 | package visibility_modifier.modifier_class.default_; 2 | 3 | /** 4 | * Desc: 5 | * Created by Chiclaim on 2018/9/21. 6 | */ 7 | class JavaDefaultClass { 8 | } 9 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/visibility_modifier/modifier_class/default_/JavaDefaultClassTest.java: -------------------------------------------------------------------------------- 1 | package visibility_modifier.modifier_class.default_; 2 | 3 | /** 4 | * Desc: 5 | * Created by Chiclaim on 2018/10/18. 6 | */ 7 | public class JavaDefaultClassTest extends JavaDefaultClass { 8 | } 9 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/visibility_modifier/modifier_class/protect/ExtendJavaProtectedClass.java: -------------------------------------------------------------------------------- 1 | package visibility_modifier.modifier_class.protect; 2 | 3 | /** 4 | * Desc: 5 | * Created by Chiclaim on 2018/9/21. 6 | */ 7 | 8 | //Java只能在同包名下可以继承 protected class 9 | 10 | 11 | public class ExtendJavaProtectedClass extends JavaProtectedClass.ProtectedClassExtend2 { 12 | } 13 | 14 | 15 | //Java可以访问同包名下的 protected class 16 | 17 | class UseProtectedJavaClass { 18 | private JavaProtectedClass.ProtectedClassExtend2 protectedClass; 19 | } 20 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/visibility_modifier/modifier_class/protect/ExtendKotlinProtectedClass.kt: -------------------------------------------------------------------------------- 1 | package visibility_modifier.modifier_class.protect 2 | 3 | import visibility_modifier.modifier_class.protect.ProtectedClassTest 4 | 5 | /** 6 | * Desc: 7 | * Created by Chiclaim on 2018/9/21. 8 | */ 9 | 10 | //---- Kotlin就算同包名下也不能直接继承 protected class 这和Java不一样 11 | class ExtendKotlinProtectedClass //: ProtectedClassTest.ProtectedClass() 12 | 13 | //---- Kotlin就算同包名下也不能访问 protected class 14 | class UseKotlinProtectedClass { 15 | //private var protectedClass: ProtectedClassTest.ProtectedClass? = null 16 | } 17 | 18 | 19 | //----------------------------------------------------------// 20 | 21 | //既然Kotlin不能访问和继承同包名下的 protected class,那么 protected class 不就和 private class 一样了吗? 22 | 23 | //在Kotlin中要是使用 protected class ,需要继承 protected class的外部类,然后我们就可以使用 它里面的 protected class了 24 | 25 | //如果外部类不能被继承,那里面的 protected class 和 private class 没有区别,在这种情况下,编译器也建议我们把 protected 改成 private 26 | 27 | 28 | class ExtendKotlinProtectedClass2 : ProtectedClassTest() { 29 | 30 | private var protectedClass: ProtectedClass? = null 31 | 32 | // 外部类ExtendKotlinProtectedClass2继承ProtectedClass的外部类,才能让 A 继承 ProtectedClass 33 | protected class A : ProtectedClass() { 34 | 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/visibility_modifier/modifier_class/protect/JavaProtectedClass.java: -------------------------------------------------------------------------------- 1 | package visibility_modifier.modifier_class.protect; 2 | 3 | /** 4 | * Desc: 5 | * Created by Chiclaim on 2018/9/21. 6 | */ 7 | 8 | public class JavaProtectedClass { 9 | 10 | protected static class JavaProtected { 11 | protected void add() { 12 | System.out.println("add..."); 13 | } 14 | } 15 | 16 | public static class ProtectedClassExtend extends JavaProtected { 17 | 18 | } 19 | 20 | protected static class ProtectedClassExtend2 extends JavaProtected { 21 | protected void add() { 22 | System.out.println("add..."); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/visibility_modifier/modifier_class/protect/ProtectedClassTest.kt: -------------------------------------------------------------------------------- 1 | package visibility_modifier.modifier_class.protect 2 | 3 | /** 4 | * Desc: kotlin protected class 演示 5 | * 6 | * Created by Chiclaim on 2018/9/21. 7 | */ 8 | open class ProtectedClassTest { 9 | 10 | //protected class 只能在当前包可见 这点和Java是一样的 11 | //继承 protected class 的类也要声明成 protected class,这是和Java不同点 12 | 13 | protected open class ProtectedClass { 14 | open fun getName(): String { 15 | return "chiclaim" 16 | } 17 | } 18 | 19 | protected class ProtectedClassExtend : ProtectedClass() { 20 | override fun getName(): String { 21 | return "yuzhiqiang" 22 | } 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/visibility_modifier/modifier_class/protect/ProtectedTopClass.java: -------------------------------------------------------------------------------- 1 | package visibility_modifier.modifier_class.protect; 2 | 3 | /** 4 | * @author kumushuoshuo 5 | * @github https://github.com/chiclaim/ 6 | */ 7 | /*protected*/ class ProtectedTopClass { 8 | } 9 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/visibility_modifier/modifier_member/MemberModifier.kt: -------------------------------------------------------------------------------- 1 | package visibility_modifier.modifier_member 2 | 3 | /** 4 | * Desc: 5 | * Created by Chiclaim on 2018/9/21. 6 | */ 7 | open class MemberModifier { 8 | 9 | //default is public 10 | public val username: String? = "chiclaim" 11 | 12 | //visible in file 13 | private var password: String? = "123456" 14 | 15 | //visible in module 16 | internal val gender: Int = 0 17 | 18 | //visible in subclass 19 | protected var asset: Float = 100000f 20 | 21 | 22 | 23 | //方法修饰符也是一样的 24 | } -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/visibility_modifier/modifier_member/MemberModifierJava.java: -------------------------------------------------------------------------------- 1 | package visibility_modifier.modifier_member; 2 | 3 | /** 4 | * Desc: 5 | * Created by Chiclaim on 2018/10/18. 6 | */ 7 | public class MemberModifierJava { 8 | 9 | //default, visible in same package 10 | String username = "chiclaim"; 11 | 12 | //visible in file 13 | private String password = "123456"; 14 | 15 | //visible in module 16 | //internal val gender:Int =0 17 | 18 | //visible in subclass or same package 19 | protected float asset = 100000f; 20 | } 21 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/visibility_modifier/modifier_member/MemberModifierJavaTest.java: -------------------------------------------------------------------------------- 1 | package visibility_modifier.modifier_member; 2 | 3 | /** 4 | * Desc: default只能在同包名下才能访问、protected同包名和子类都可访问 5 | * Created by Chiclaim on 2018/10/18. 6 | */ 7 | public class MemberModifierJavaTest { 8 | 9 | private MemberModifierJava memberModifier = new MemberModifierJava(); 10 | 11 | void call() { 12 | 13 | //memberModifier.asset protected 14 | //memberModifier.username public 15 | 16 | System.out.println(memberModifier.username + " has " + memberModifier.asset); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /kotlin-in-action/src/main/java/visibility_modifier/modifier_member/MemberModifierTest.kt: -------------------------------------------------------------------------------- 1 | package visibility_modifier.modifier_member 2 | 3 | /** 4 | * Desc: (相同包名)成员修饰符 演示 5 | * Created by Chiclaim on 2018/9/21. 6 | */ 7 | class MemberModifierTest { 8 | 9 | val memberModifier: MemberModifier = MemberModifier() 10 | 11 | fun call() { 12 | 13 | //memberModifier.gender internal 14 | //memberModifier.username public 15 | 16 | println("${memberModifier.username}'s gender ${memberModifier.gender}") 17 | } 18 | } 19 | 20 | //继承 21 | class MemberModifierTest2 : MemberModifier() { 22 | fun call() { 23 | //gender //internal 24 | //username //public 25 | //asset //protected 26 | 27 | println("$username's gender $gender, He has $asset") 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /other-module/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | !**/src/main/**/build/ 5 | !**/src/test/**/build/ 6 | 7 | ### IntelliJ IDEA ### 8 | .idea/modules.xml 9 | .idea/jarRepositories.xml 10 | .idea/compiler.xml 11 | .idea/libraries/ 12 | *.iws 13 | *.iml 14 | *.ipr 15 | out/ 16 | !**/src/main/**/out/ 17 | !**/src/test/**/out/ 18 | 19 | ### Eclipse ### 20 | .apt_generated 21 | .classpath 22 | .factorypath 23 | .project 24 | .settings 25 | .springBeans 26 | .sts4-cache 27 | bin/ 28 | !**/src/main/**/bin/ 29 | !**/src/test/**/bin/ 30 | 31 | ### NetBeans ### 32 | /nbproject/private/ 33 | /nbbuild/ 34 | /dist/ 35 | /nbdist/ 36 | /.nb-gradle/ 37 | 38 | ### VS Code ### 39 | .vscode/ 40 | 41 | ### Mac OS ### 42 | .DS_Store -------------------------------------------------------------------------------- /other-module/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'org.jetbrains.kotlin.jvm' version '1.8.21' 4 | } 5 | 6 | group = 'org.example' 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | testImplementation platform('org.junit:junit-bom:5.9.1') 14 | testImplementation 'org.junit.jupiter:junit-jupiter' 15 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" 16 | implementation project(":kotlin-in-action") 17 | } 18 | 19 | test { 20 | useJUnitPlatform() 21 | } 22 | kotlin { 23 | jvmToolchain(11) 24 | } -------------------------------------------------------------------------------- /other-module/src/main/java/visibility_modifier/GetInternalClass.kt: -------------------------------------------------------------------------------- 1 | package visibility_modifier 2 | 3 | import base.Person 4 | 5 | /** 6 | * desc: 演示调用另一个模块的 internal 修饰的类 7 | * 8 | * Created by Chiclaim on 2018/09/20 9 | */ 10 | 11 | fun getInternalClassFromOtherModule() { 12 | //Person class is in another module 13 | val p1 = Person("yuzhiqiang") 14 | 15 | //----Can't resolve InternalClass,It's internal class in another module 16 | //val p2 = InternalClass() 17 | 18 | println(p1.name) 19 | } -------------------------------------------------------------------------------- /other-module/src/main/java/visibility_modifier/MemberModifierTest.kt: -------------------------------------------------------------------------------- 1 | package visibility_modifier 2 | 3 | import visibility_modifier.modifier_member.MemberModifier 4 | 5 | /** 6 | * Desc: 7 | * Created by Chiclaim on 2018/9/21. 8 | */ 9 | 10 | //在不同模块测试访问修饰符 11 | class MemberModifierTest { 12 | 13 | private val memberModifier: MemberModifier = MemberModifier() 14 | 15 | 16 | fun call() { 17 | println("${memberModifier.username}") 18 | } 19 | 20 | 21 | } 22 | 23 | fun main(args: Array) { 24 | MemberModifierTest().call() 25 | } -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | 2 | rootProject.name = 'KotlinTutorials' 3 | include 'kotlin-in-action' 4 | include 'other-module' 5 | 6 | -------------------------------------------------------------------------------- /src/main/kotlin/Main.kt: -------------------------------------------------------------------------------- 1 | 2 | fun main(args: Array) { 3 | println("Hello World!") 4 | 5 | // Try adding program arguments via Run/Debug configuration. 6 | // Learn more about running applications: https://www.jetbrains.com/help/idea/running-applications.html. 7 | println("Program arguments: ${args.joinToString()}") 8 | 9 | } --------------------------------------------------------------------------------