全部 文章 问答 分享 共找到42个相关内容
[分享] Rxjava源码阅读指南
本文不对Rxjava的基本使用进行讲解,仅对源码做分析,如果你对Rxjava的基本使用还有不清楚的,建议学习官方文档之后再阅读本文 本文会逐一解析Rxjava的create()、subscribe
2020-02-06 12:39 · Android / RxJava / 源码 / 异步
[文章] CSS如何实现文章展开阅读全文的效果?
CSS如何实现文章展开阅读全文的效果?很多网站都有这样的功能?我也不知道为什么需要这个功能,展开阅读。先是只能见一部分。
2020-03-06 15:10 · 前端 / CSS / 阅读全文
[文章] 安卓端sob_blog解析阅读MarkDown文章
作为一名学习安卓的小菜鸡,自然希望在安卓上也能阅读我们写的文章。所以如果能在安卓上显示MarkDown,那可真是太爽了。考虑到前几天大锯老师在VUE里面引入了一个mavon-editor的库。
2020-08-09 17:13 · 安卓 / markDown / 源码
[文章] 《Kotlin 核心编程》阅读笔记
@[TOC](《Kotlin核心编程》阅读笔记)第四章代数数据类型和模式匹配代数数据类型(ADT)在计算机编程中,特别是函数式编程与类型理论中,ADT是一种组合类型(compositetype)。
1970-01-01 00:00 · kotlin
[分享] Android上层应用源代码
在我们学习内容提供者的时候,我们需要去阅读Android上层应用的源码,在我们学习四大组件的时候,想去打开相机呀,设置呀,系统原生应用的时候。我们需要去阅读源码,查看里的意图过滤规则。
2019-10-27 22:04 · 安卓 / 源码 / 应用 / android / app
[文章] 《kotlin核心编程》阅读笔记 第九章 设计模式
@[TOC](《kotlin核心编程》阅读笔记第九章设计模式)第九章设计模式基于Kotlin崭新的语言特性,实现或替换了Java中部分典型设计模式。
1970-01-01 00:00 · kotlin
2019-11-18 17:27 · 美团 / 饿了么 / 分类 / 轮播图 / 安卓
[文章] google广告新创建的页面无法加载
google广告新创建的页面无法加载我一直以为是自己的问题整天在找原因,去分析别人的网站查看源码阅读英文资料然后发现别人的网站也是不行的。那怎么整呢?只能从产品的角度去优化这个问题了。晕菜。
2020-05-09 01:55 · google / 广告 / 加载 / adsense / 谷歌
[分享] 喜马拉雅FM电台项目代码
另外一个则是提高同学们的代码阅读能力。如果学习中遇到问题的话,可以发帖子提问交流,感谢大家的支持!
[问答] 这段代码我明明写了右边却没有显示右边
layout_centerHorizontal="true"android:layout_alignParentBottom="true"android:layout_marginBottom="50dp"android:text="登录即代表阅读并同意阅读条款
2019-12-05 15:00 · 代码与视频教程的问题
[文章] 《Kotlin》阅读笔记 第八章 元编程
@TOC第八章元编程Java的反射只是元编程的一种方式。示例:将dataclass转换成Map的例子。dataclassUser(valname:String,valage:Int){funtoMap(a:User):Map<String,Any>{returnhashMapOf("name"toname,"age"toage)}}这样实现有一个缺点:对每一个新的类型我们都需要重复实现toMap函数,因为每个类型都拥有不同的属性。程序和数据通过反射实现:dataclassUser(valname:String,valage:Int){funtoMap():Map<String,Any>{returnhashMapOf("name"toname,"age"toage)}}objectMapper{fun<A:Any>toMap(a:A):Map<String,Any?>{//获取A中的所有属性returna::class.memberProperties.map{m->valp=masKProperty<*>p.nametop.call(a)}.toMap()}fun<A:Any>toMap1(a:A)=run{//获取A中的所有属性a::class.memberProperties.map{m->valp=masKProperty<*>p.nametop.call(a)}.toMap()}}funmain(){for(entry1inUser("Kar",19).toMap()){println("${entry1.key}---->${entry1.value}")}for(entryinMapper.toMap(User("Jack",20))){println("${entry.key}---->${entry.value}")}for(entryinMapper.toMap1(User("Tom",18))){println("${entry.key}---->${entry.value}")}}上面代码中的两个toMap方法,是类似的。这里的a::class的类型是KClass,是Kotlin中描述类型的类型(也称为metaclass);在传入参数类型为User时,a::class则可以描述User类型的数据。这样描述数据的数据就称为元数据。什么是元编程操作元数据的编程就是元编程。程序即是数据,数据即是程序。这句话包含两个意思:前半句指的是访问描述程序的数据,如我们通过反射获取类型信息。后半句则是指:将这些数据转化成对应的程序,也就是所谓的代码生成。元编程就像高阶函数一样,是一种更高阶的抽象,高阶函数将函数作为输入或输出,而元编程则是将程序本身作为输入或输出。常见的元编程技术运行时通过API暴露程序信息反射;动态执行代码多见于脚本语言。如JavaScript就有eval函数,可以动态地将文本作为代码执行。通过外部程序实现目的如编译器,在将源文件解析成AST之后,可以针对这些AST做各种转化。这种实现思路最典型的例子是我们常常谈论的语法糖,编译器会将这部分代码AST转化为相应的等价的AST,这个过程通常被称为desuger(解语法糖)。AST:抽象语法树是源代码语法结构的一种抽象表示;它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。之所以说语法是“抽象”的,是因为这里的语法并不会表示出真实语法中出现的每一个细节。比如,嵌套括号被隐含在树的结构中,并没有以节点的形式呈现;而类似于if-condition-then这样的条件跳转语句可以使用带有两个分支的节点来表示。反射,有时候也称为自反,是指元语言(即前文提到的描述程序的数据结构)和要描述的语言是同一种语言的特性。除了运行时反射之外,也有许多语言支持编译期反射,编译期反射通常需要宏等技术结合实现,编译器将当前程序的信息作为输入传入给宏,将其结果作为程序的一部分。宏:Koltin不支持宏。模板元编程:和Kotlin关系并不大。Kotlin的反射kotlin和Java反射Kotlin的KClass和Java的Class可以看作同一个含义的类型,并且通过.java和.kotlin方法在KClass和Class之间相互转化。Kotlin中的KCallable和Java的AccessiableObject都可以理解为可调用元素。Java中构造方法为一个独立的类型,而Kotlin则统一作为KFunction处理。Koltin中的KProperty和Java的Filed不太相同,Koltin的KProperty通常指相应的Getter和Setter(只有可变属性Setter)整体作为一个KProperty(通常情况Kotlin并不存在字段的概念),而Java的Field通常仅仅指字段本身。koltin的KClassKCLass的特别属性或函数特别属性或函数|含义--------|-----isCompanion|是否伴生对象isData|是否数据类isSealed|是否密封类objectInstance|object实例(如果是object)companionObjectInstance|伴生对象实例declareMemberExtensionFunctions|扩展函数declareMemberExtensionProperties|扩展属性memberExtensionFunction|本类及超类扩展函数memberExtensionProperties|本类及超类扩展属性starProjectedType|泛型通配类型示例:获取object实例sealedclassNat{companionobject{objectZero:Nat()}valCompanion._0get()=Zerofun<A:Nat>Succ<A>.proceed():A{returnthis.prev}}dataclassSucc<N:Nat>(valprev:N):Nat()fun<A:Nat>Nat.plus(other:A):Nat=when{otherisSucc<*>->Succ(plus(other.prev))else->this}funmain(){println(Nat.Companion::class.isCompanion)//trueprintln(Nat::class.isSealed)//trueprintln(Nat.Companion::class.objectInstance)//chapter8.Nat$Companion@646be2c3println(Nat::class.companionObjectInstance)//chapter8.Nat$Companion@646be2c3println(Nat::class.declaredMemberExtensionFunctions.map{it.name})//[proceed]println(Nat::class.declaredMemberExtensionProperties.map{it.name})//[_0]'println(Succ::class.declaredMemberExtensionProperties.map{it.name})//[]println(Succ::class.declaredMemberExtensionFunctions.map{it.name})//[]println(Succ::class.declaredMemberExtensionProperties.map{it.name})//[]println(Succ::class.memberExtensionProperties.map{it.name})//[_0]println(Succ::class.memberExtensionFunctions.map{it.name})//[proceed]println(Succ::class.starProjectedType)//chapter8.Succ<*>println(Nat::class.memberExtensionFunctions.map{it.name})//[proceed]}kotlin的KCallable如何获取Class的成员:通过members方法,它的返回值是一个Collection<KCallable<*>>。KCallable提供的APIKCallable提供的API|含义--------|-----isAbstract:Boolean<KParameter>|此KCallable是否为抽象的isFinal:Boolean|此KCallable是否为finalisOpen:Boolean|此KCallable是否为openname:string|此KCallable的名称parameters:List<KParameter>|调用此KCallable需要的参数returnType:KType|此KCallable的返回类型typeParameters:List<KTypeParameter>|此KCallable的类型参数visibility:KVisibility?|此KCallable的可见性call(varargargs:Any?):R|给定参数调用此KCallablefunmain(){val_1=Succ(Nat.Companion.Zero)valpreceed=_1::class.members.find{it.name=="proceed"}println(preceed?.call(_1,_1)==Nat.Companion.Zero)}上面代码通过反射执行Succ的扩展函数proceed,这里传入了两个Nat对象,因为执行扩展函数时,除了参数实例外,需要传入接受者实例。在Kotlin中,并不是所有的属性都是可变的,因此我们只能对那些可变的属性进行修改操作。KMutableProperty是KProperty的一个子类。使用When表达式来识别属性。dataclassPerson(valname:String,valage:Int,varaddress:String)funKMutablePropertyShow(){valp=Person("YanLq",22,"SWPU")valprops=p::class.memberPropertiesfor(propinprops){when(prop){isKMutableProperty<*>->prop.setter.call(p,"DZ")else->prop.call(p)}}println(p.address)}funmain(){KMutablePropertyShow()}获取参数信息Koltin把参数分为3个类别,分别是函数的参数(KParameter),函数的返回值(KType)以及类型参数(KTypeParameter)KParameter使用KCallable.parameters即可获取一个List<KParameter>,它代表的是函数(包括扩展函数)的参数。API描述index:Int返回该参数在参数列表里面的indexisOptiona:Boolean该参数是否为OptionalisVarags:Boolean该参数是否为varagskind:Kind该参数的kindname:String?该参数的名称type:KType该参数的类型funKParameterShow(){for(cinPerson::class.members){print("${c.name}->")for(pinc.parameters){print("${p.type}--")}println()}}funmain(){KParameterShow()}KType获取KCallable的返回值类型。每一个KCallable都可以使用returnType来获取返回值类型,它的结果类型是KType。API描述arguments:List<KtypeProjection>该类型的类型参数classifier:KClassifier该类型在类声明层面的参数,如该类型为List<String>,那么通过classifier得到结果为List(忽略类型参数)isMarkedNullable:Boolean该类型是否标记为可空类型dataclassPerson(valname:String,valage:Int,varaddress:String){funfriendsName():List<String>{returnlistOf("Yison","Jilen")}}funmain(){Person::class.members.forEach{println("${it.name}->${it.returnType.classifier}")}}>>>address->classkotlin.Stringage->classkotlin.Intname->classkotlin.Stringcomponent1->classkotlin.Stringcomponent2->classkotlin.Intcomponent3->classkotlin.Stringcopy->classchapter8.Personequals->classkotlin.BooleanfriendsName->classkotlin.collections.ListhashCode->classkotlin.InttoString->classkotlin.StringclassifierAPI其实就是获取该参数在类层面对应的类型。KTypeParameter对于函数和类来说,还有一个重要的参数——类型参数,在KClass和KCallable中我们可以通过typeParameters来获取class和callable的类型参数,它的返回结果集是List<KTypeParameter>,不存在类型参数时就返回一个空的List。dataclassPerson(valname:String,valage:Int,varaddress:String){funfriendsName():List<String>{returnlistOf("Yison","Jilen")}fun<A>get(a:A):A{returna}}funKTypeParameterShow(){for(cinPerson::class.members){if(c.name.equals("get")){println(c.typeParameters)}}vallist=listOf<String>("How")println(list::class.typeParameters)}funmain(){KTypeParameterShow()}>>>[A][E]Kotlin注解Kotlin的注解创建语法:annotationclassFooAnnotation(valbar:String)注解koltin.Metadata这是实现Kotlin大部分独特特性反射的关键,Koltin将这些信息直接以注解形式存储在字节码文件中,以便运行时发射可以获取这些数据。和Java一样注解的参数只能是常量,并且仅支持下列类型:与Java对应的基本类型字符串Class对象(KClass或者Java的Class)其他注解上述类型数组。基本类型数组需要指定为对应的XXXArray,如:IntArray而不是Array<Int>/标注在注解上的注解我们称之为元注解。Java有下列5个元注解。-Documented文档(通常是API文档)中必须出现给注解。-Inherited如果超类标注了该类型,那么其子类型也将自动标注该注解而无需指定。-Repeatable这个注解在同一位置可以出现多次。-Retention表述注解用途。有三种取值。-Sourc仅在源代码中存在,编译后的class文件不包含该注解信息。-CLASSclass文件中存在该注解,但不能被反射读取。-RUNTIME注解信息同样保存在class文件中并且可以在运行时通过反射获取。-Target表明注解可应用于何处。Kotlin也有相应类似的元注解在kotlin.annotation包下。Kotlin和Java的注解整体上保持一致。Koltin目前不支持Inherited。无处不在的注解Kotlin(AnnotationTarget)Java(Target)说明CLASSTYPE作用于类ANNOTATION_CLASSANNOTATION_TYPE作用于注解本身(即元注解)TYPE_PARAMETERTYPE_PARAMETER作用于类型参数PROPERTYNA作用于属性FIELDFIELD作用于字段(属性通常包含字段Getter以及Setter)LOCAL_VARIABLELOCAL_VARIABLE作用于局部变量VALUE_PARAMETERNA作用于val参数CONSTRUCTORCONSTRUCTOR作用于构造函数FUNCTIONMETHOD作用于函数(Java只有method)PROPERTY_GETTERNA作用于GetterPROPERTY_SETTERNA作用于SetterTYPETYPE_USE作用于类型EXPRESSIONNA作用于表达式FILEPACKAGE作用于文件开头/包声明TYPEALIASNA作用于类型别名annotationclassCache(valnamespace:String,valexpires:Int)annotationclassCacheKey(valkeyName:String,valbuckets:IntArray)@Cache(namespace="hero",expires=3600)dataclassHero(@CacheKey(keyName="heroName",buckets=intArrayOf(1,2,3))valname:String,valattack:Int,valdefense:Int,valinitHp:Int)精准控制注解位置假设我们有注解annotationclassCacheKey。精准的注释控住语法:用法|含义-|-@file:CacheKey|CacheKey注解作用于文件@property:CacheKey|CacheKey注解作用于属性@field:CacheKey|CacheKey注解作用于字段@get:CacheKey|CacheKey注解作用于Getter@set:CacheKey|CacheKey注解作用于Setter@receiver:CacheKey|CacheKey注解作用于扩展函数或属性@param:CacheKey|CacheKey注解作用于构造函数参数@setParam:CacheKey|CacheKey注解作用Setter的参数@delegate:CacheKey|CacheKey注解作用于存储代理实例的字段@Cache(namespace="hero",expires=3600)dataclassHero(@property:CacheKey(keyName="heroName",buckets=[1,2,3])valname:String,@field:CacheKey(keyName="atk",buckets=[1,2,3])valattack:Int,@get:CacheKey(keyName="def",buckets=[1,2,3])valdefense:Int,valinitHp:Int)获取注解信息代码标记上注解以后,注解本身也成为了代码的一部分。我们可以获取注解信息。通过反射获取注解信息但是前提是这个注解的Retention标注为Runtime或者没有显示注定(默认为Runtime)。annotationclassCache(valnamespace:String,valexpires:Int)annotationclassCacheKey(valkeyName:String,valbuckets:IntArray)@Cache(namespace="hero",expires=3600)dataclassHero(@CacheKey(keyName="heroName",buckets=[1,2,3])valname:String,valattack:Int,valdefense:Int,valinitHp:Int)funmain(args:Array<String>){valcacheAnnotation=Hero::class.annotations.find{itisCache}asCache?println("namespace->${cacheAnnotation?.namespace}")println("expires->${cacheAnnotation?.expires}")}>>>namespaceheroexpires3600通过反射获取注解信息是在运行时发生的。注解标准位置也会影响注解信息的获取。注解处理器JSR269引入了注解处理器(annotationprocessors),允许在编译过程中挂钩子实现代码生成,得益于此,如dagger之类的框架实现了编译时依赖注入这样原本只能通过运行时反射支持的特性。importjavax.annotation.processing.AbstractProcessorimportjavax.annotation.processing.RoundEnvironmentimportjavax.lang.model.element.ElementKindimportjavax.lang.model.element.TypeElementimportkotlin.reflect.full.memberPropertiesannotationclassMapperAnnotationclassMapperProcessor:AbstractProcessor(){privatefungenMapperClass(pkg:String,clazzName:String,props:List<String>):String{return"""package$pkgimportjava.utils.*;publicclass${clazzName}Mapper{publicMap<String,Object>toMap($clazzNamea){Map<String,Object>m=newHashMap<String,Object>();${props.map{"m.put(\"${it}\",a.${it})"}}}}""".trimIndent()}overridefunprocess(annotations:MutableSet<outTypeElement>?,roundEnv:RoundEnvironment?):Boolean{valel=roundEnv?.getElementsAnnotatedWith(MapperAnnotation::class.java)?.firstOrNull()if(el?.kind==ElementKind.CLASS){valpkg=el.javaClass.`package`.namevalcls=el.javaClass.simpleNamevalprops=el.javaClass.kotlin.memberProperties.map{it.name}valmapperClass=genMapperClass(pkg,cls,props)valjfo=processingEnv.filer.createSourceFile("${cls}Mapper")valwriter=jfo.openWriter()writer.write(mapperClass)writer.close()}returntrue}}我还不太会注解。不知道咋运行。
1970-01-01 00:00 · kotlin
[文章] Android开发RecyclerView的适配器notifyDataSetChange做了什么?
接下来我们就阅读一下源码,adapter跟recyclerView是如何通讯的!
2019-11-02 21:05 · RecyclerView / 安卓开发 / 适配器 / adapter
[文章] 《Kotlin核心编程》阅读笔记 第五章 类型系统
第五章类型系统null引用在Java中如何解决空指针异常:函数内对于无效值,更倾向于抛异常处理。采用@NotNull/@Nullable标注使用专门的Optional对象对可能为null的变量就行装箱。可空类型在Kotlin中,可以在任何类型后面加上“?"Int?等同于Intornull由于null只能被存储在Java的引用类型中,所以在Kotlin中基本数据类型的可空版本都会使用该类型的包装形式,同样,如果使用基本数据类型作为泛型类的类型参数,Koltin同样会使用该类型的包装类。-安全调用"?."XXX?.YYY:当XXX不为null,才调用YYY-Elvis操作符"?:"或合并操作符。-非空断言"!!"类型检查:在Koltin中用is代替Java中的instanceof当类型需要强制转换时,可以利用"as"操作符来实现。Any:非空类型的根类型Kotlin把Java方法参数和返回类型中用到的Object类型看作Any(更确切的说是当作“平台类型”);Any?:所有类型的根类型。Nothing与Nothing?:Kotlin类型层级结构的最底层是Nothing类型。Nothing是没有实例的类型,Nothing类型的表达式不会产生任何值。它只能包含一个值“null”。自动装箱和拆箱Kotlin中的Int类型等同于int;Kotlin中的Int?等同于Integer;Kotlin中有Array,但是并不是一种原生的数据结构,而是一种Array类。甚至我们可以将Kotlin中的Array视作为集合类的一部分。Kotlin中还为原始类型额外引入了一些实用类:IntArray,CharArray,ShortArray等。分别对应了Java中的int[]、char[]、short[].IntArray等并不是Array的子类。Kotlin对原始类型有特殊优化,推荐使用原始类型数组。泛型将参数的类型进行参数化。泛型的优势:类型检查,能在编译时就帮你检查出错误。更加语义化,比如声明一个List<String>,便可以知道里面存储的是String对象,自动类型转换,获取数据时不需要进行类型强制转换;能写出更加通用的代码。在Kotlin中使用泛型的格式也是<T>,<S>类似的。声明一个泛型类和泛型函数:实现定义一个find方法,传入一个对象,若列表中存在该对象,就返回该对象,不存在则返回空;classSmartList<T>:ArrayList<T>(){funfind(t:T):T?{valindex=super.indexOf(t)returnif(index>=0)super.get(index)elsenull}}funmain(){valsmartList=SmartList<String>()smartList.add("qq")println(smartList.find("qq"))println(smartList.find("aa"))}除了上述做法,还可以有扩展函数;funmain(){valarrayList=ArrayList<String>()arrayList.add("qq")println(arrayList.find("qq"))println(arrayList.find("aa"))}fun<T>ArrayList<T>.find(t:T):T?{valindex=this.indexOf(t)returnif(index>=0)this[index]elsenull}类型约束:设定类型上界;示例;需求为:有一把刀只能用来切长在地上的水果(如西瓜)interfaceGround{}openclassFruit(valweight:Double)classApple(weight:Double):Fruit(weight)classBanana(weight:Double):Fruit(weight)classFruitPlate<T:Fruit>(valt:T)//:类型约束,表示只能装水果的盘子classWatermelon(weight:Double):Fruit(weight),Groundfun<T>cut(t:T)whereT:Fruit,T:Ground{println("Youcancut")}funmain(){cut(Watermelon(5.0))}通过where关键字,他可以实现泛型参数类型添加多个约束条件。上面的泛型是在静态时的行为,也就是Kotlin代码编译阶段关于泛型的知识点。publicclassTestArray{publicstaticvoidmain(String[]args){Apple[]applyArray=newApple[10];Fruit[]fruitArray=applyArray;//fruitArray[0]=newBanana(0.5);List<Apple>appleList=newArrayList<Apple>();//List<Fruit>fruitList=appleList;System.out.println(applyArray.getClass());System.out.println(appleList.getClass());}}>>>class[Lchapter5.Apple;>>>classjava.util.ArrayList数组是协变的,而List是不变的。简单来说就是Object[]是所有对象数组的父类,而List<Object>却不是List<T>的父类。从上面的打印结果可以知道,数组在运行时是可以获取自身的类型,而List<Apple>在运行时只知道自己是一个List,而无法获取泛型参数的类型。而Java数组是协变的,也就是说任意的类A和类B,若A是B的父类,则A[]也是B[]的父类。但是假如给数组加入泛型后,将无法满足数组协变的原则,因为在运行时无法知道数组的类型。Kotlin中的泛型机制和Java中是一样的,上面的特性Kotlin中也存在。类型擦除:Java受限于先后兼容的困扰,使用了类型擦除来实现了泛型,但是它还是通过其他方式来保证了泛型的相关特性。泛型在编译后是会擦除泛型类型的,而泛型的一些相关特性,比如类型检查是在编译器在编译前就会帮我们进行类型检查,类型自动转换是通过强制类型转化来实现的。类型擦除的矛盾:在某些场景需要知道运行时泛型参数类型。既然编译后会擦除泛型参数类型,那我们是不是可以主动指定参数类型来达到运行时获取泛型参数类型的效果呢?funmain(){valapplePlate=Plate(Apple(1.0),Apple::class.java)applePlate.getType()}openclassPlate<T>(valt:T,privatevalclazz:Class<T>){fungetType(){println(clazz)}}使用这种方法确实可以到达运行时获取泛型类型参数的效果,但是这样也有限制。vallistType=ArrayList<String>()::class.java//不被允许还可以使用匿名内部类来是实现。funmain(){vallist1=ArrayList<String>()vallist2=object:ArrayList<String>(){}println(list1.javaClass.genericSuperclass)println(list2.javaClass.genericSuperclass)}>>>java.util.AbstractList<E>java.util.ArrayList<java.lang.String>现在可以设计一个能获取到所有类型信息的泛型类:importjava.lang.reflect.ParameterizedTypeimportjava.lang.reflect.TypeopenclassGenericsToken<T>{vartype:Type=Any::class.javainit{valsuperClass=this.javaClass.genericSuperclasstype=(superClassasParameterizedType).actualTypeArguments[0]}}funmain(){valgt=object:GenericsToken<Map<String,String>>(){}println(gt.type)}Gson也是使用的类似方法。在Kotlin中除了用这种方式来获取泛型参数类型以外,还有另一种方式——内联函数。Kotlin中的内联函数在编译的时候编译器便会将相应函数的字节码插入调用的地方。Java并不支持主动指定一个函数是否是内联函数,所有在Kotlin中声明的普通内联函数可以在Java中调用,因为他不会被当做一个常规函数;而用reified来实例化的参数类型的内联函数则不能在Java中调用,因为它永远是需要内联的。打破泛型不变Kotlin中的List与Java的List有区别虽然都叫List,也同样支持泛型,但是Kotlin中的List定义的泛型参数前面多了一个out关键字。这个关键字就对这个List的特性起到了很大作用。普通方式定义的泛型是不变的,简单来说就是不管类型A和类型B是什么关系,Generic<A>与Generic<B>(Generic代表泛型类)都没有任何关系。在Java中String是Object的子类型,但是List<String>并不是List<Object>的子类型。在Kotlin中泛型的原理是一样的。但是,Kotlin的List为什么允许List<String>赋值给List<Any>呢?一个支持协变的List如果在定义泛型类和泛型方法的泛型参数前面加上out关键词,说明这个泛型类及泛型方法是协变的。类型A是类型B的子类型,那么Generic<A>也是Generic<B>的子类型。因为Kotlin的List支持协变,所以他无法添加元素,只能从里面读取内容;List一旦创建就不能再被修改。这便是将泛型声明为协变需要付出的代价。通常情况下,若一个泛型类Generic<outT>支持协变,那么它里面的方法的参数类型就不能使用T类型,因为一个方法的参数不允许传入参数父类型的对象,可能会导致错误。可以添加**@UnsafeVariance**注解来解除这个限制。一个支持逆变的Comparator逆变:类型A是类型B的子类型,但是Generic<B>反过来又是Generic<A>的子类型。加上现在需要对一个**MutableList<Double>**进行排序,利用其sortWith方法,我们需要传入一个比较器:valdoubleComparator=Comparator<Double>{d1,d2->d1.compareTo(d2)}funmain(){valdoubleList=mutableListOf(2.0,3.0)doubleList.sortWith(doubleComparator)for(iindoubleList){print("$i")}}但是如果又需要对MutableList<Int>,**MutableList<Long>**等进行排序,那我们可能又需要定义不同的Comparator。试想定义一个比较器,给这些列表用,这些数字类的共同父类是Number类。valnumberComparator=Comparator<Number>{num1,num2->num1.toDouble().compareTo(num2.toDouble())}funmain(){valdoubleList=mutableListOf(2.0,3.0)doubleList.sortWith(numberComparator)for(iindoubleList){print("$i")}println()valintList=mutableListOf(5,1)intList.sortWith(numberComparator)for(iinintList){print("$i")}}结果是成功运行了,这说明是可以这样做的。publicfun<T>kotlin.collections.MutableList<T>.sortWith(comparator:kotlin.Comparator<inT>/*=java.util.Comparator<inT>*/):kotlin.Unit{/*compiledcode*/}这里又出现了一个in关键词、和out类似,它也是泛型有个另一个特性——逆变:类型A是类型B的子类型,但是Generic<B>反过来又是Generic<A>的子类型。用out关键字声明的泛型参数类型将不能作为方法的参数类型,但是可以作为方法的返回值类型。而in刚好相反。协变和逆变类型通配符代替泛型参数,Java中的泛型类型通配符为"?",而Koltin中用"*"来表示类型通配符。
1970-01-01 00:00 · kotlin
[问答] Android项目的 “移植” “引用” 问题
或者有什么文章是讲述类似操作的我一定好好阅读、万分感谢!!!
2020-06-18 12:17 · anroid
[文章] 【领券联盟】笔记:视频46,47,48,49-解决刷新控件的事件冲突问题
mRecyclerView.canScrollVertically(1);}returnfalse;}代码很少,老师讲的很多很细,具体内容原理请看视频视频链接【领券联盟】46-添加refresh刷新控件的模块依赖【领券联盟】47-阅读刷新控件的源码
2020-04-02 19:41 · 课堂笔记
[文章] 《Kotlin核心编程》阅读笔记 第七章 多态和扩展
@TOC第七章多态和扩展Kotlin的扩展其实多态的一种表现形式。多态的不同方式多态是面向对象程序设计的一个重要特性。当用一个子类继承一个父类的时候,这就是子类型多态(Subtypepolymorphism)。另一种熟悉的多态是参数多态(Parametricpolymorphism)。子类型多态用子类型替换超类型实例的行为,就是子类型多态。参数多态理解起来像是把参数抽成一个类型,类似泛型的感觉。对第三方进行扩展即扩展函数。扩展属性和扩展方法的实现是运行在类的实例上,不会修改类本身。特设多态和运算符重载特设多态:一个多态函数是有多个不同的实现,依赖于其实参而调用相应版本。operator:将一个函数标记为重载一个操作符或者和实现一个约定。dataclassArea(valvalue:Double)operatorfunArea.plus(that:Area):Area{returnArea(this.value+that.value)}funmain(){println(Area(1.0)+Area(2.0))}还可以重载减法minus、乘法times、除法div等扩展:为别的类添加方法、属性扩展与开放封闭原则软件实体应该是可扩展,而不可修改的。开放封闭原则开放封闭原则(OCP:OpenClosedPrinciple)是所有面向对象原则的核心。软件设计本身所追求的目标就是封装变化、降低耦合,而开放封闭原则正是对这一目标的最直接体现。其他的设计原则,很多时候是为了实现这一目标服务的,例如以替代原则实现最佳、正确的继承层次,就能保证不会违背开放封闭原则。使用扩展函数、属性funMutableList<Int>.exchange(fromIndex:Int,toIndex:Int){valtmp=this[fromIndex]this[fromIndex]=this[toIndex]this[toIndex]=tmp}这里扩展函数体里的this代表的是接收者类型的对象。标准库中的扩展函数:run、let、also、takeIfrunrun方法的定义:publicinlinefun<T,R>T.run(block:T.()->R):R=block()run是任何类型T的通用扩展函数,run中执行了一个返回值类型为R的扩展函数block,最终返回扩展函数的结果。let定义:publicinlinefun<T,R>T.let(block:(T)->R):R=block(this)let返回的是闭包里面的值。dataclassStudent(age:Int)classKot{valstudent:Student?=getStu()fundealStu(){valresult=student?.let{println(it.age)it.age}}}also定义:publicinlinefun<T>T.also(block:(T)->Unit):T{block(this)returnthis}函数的返回值是该函数的接收者。classKot{valstudent:Student?=getStu()fundealStu(){valresult=student?.also{stu->this.age+=stu.ageprintln(this.age)println(stu.age)this.age}}}takeIf如果我们不仅仅只想判断空,还想加入条件,这是let可能显得有点不足。定义:publicinlinefun<T>T.takeIf(predicate:(T)->Boolean):T?=if(predicate(this))thiselsenull当接收器满足某些条件才会执行。把之前的也写一下:with和applywith的定义:inlinefun<T,R>with(receiver:T,block:T.()->R):Rwith的第一个参数为接收者类型,然后通过第二个参数创建这个类型的block方法。apply的定义:inlinefun<T>T.apply(block:T.()->Unit):T看这些定义还是有点晕的。写代码时,在编译器的提示感觉会好点。
1970-01-01 00:00 · kotlin
[文章] 程序员必做的文史题目
——《庄子》B:贪心;回溯;穷举;分治;递归;三、阅读理解(阅读下文,回答后面的问题):美国的贝尔实验室设计了最初的C语言刻在UNIX操作系统距今已有三四十年你在屏幕前凝视数据的缱绻我却在旁轻轻敲打键盘把你的梦想展现循环递归贪心动规是谁的从前喜欢在匈牙利算法中你我牵手的画面经过
2019-10-21 12:37 · 搞笑 / 程序员 / 日常
[文章] 程序员如何解决问题呢?
代码阅读:开源的代码没有秘密,里面的实现原理都给你看了,你还想怎么样呢?所以大家要提升自己的代码阅读能力。一些IDE的快捷键,使用技巧,debug技巧。
2019-11-02 03:41 · 奇淫技巧 / 程序员 / 解问题 / bug / 程序猿
[文章] 前端css的心得(非专业前端开发)
载入样式的时候两个都载入,方便管理和阅读。如果服务器资源更新了,如何让浏览器加载新的内容呢?后台如何通过代码让浏览器更新静态资源?
2020-01-17 12:58 · css / html / 样式 / 前端
[问答] leetcode面试题 17.16. 按摩师 代码提交执行超时
https://leetcode-cn.com/problems/the-masseuse-lcci/阅读前两个提示之后尝试递归解决测试用例:[104,209,137,52,158,67,213,86,141,110,151,127,238,147,169,138,240,185,246,225,147,203,83,83,131,227,54,78,165,180,214,151,111,161,233,147,124,143
2020-03-24 13:13 · JavaScript
[文章] 你的2019总结来了吗?【有奖征文】
2019和展望2020可以是以下题材:年终总结所学习到的内容技术文章求职经历,经验2020目标规则参与条件:注册用户评分规则评审团打分:占5分(注重内容)点赞数:占4分(文章末尾可以提示用户喜欢的话点赞)阅读
[文章] 图片上传重构点记录(2021-2-24)
感谢阅读。感谢大家的建议!其实我昨晚写好了,我现在没法截图,不在家里,哈哈。
2021-02-24 16:01 · 日常 / 后台 / javaweb / 重构 / 记录
[文章] Jetpack-Lifecycle
源码分析源码分析我们分为:View层生命周期变化如何通知LifecycleLifecycle如何通知观察者View层生命周期变化一般来说,我们阅读源码的时候,要带着问题去阅读
2020-10-09 16:58 · Lifecycle / 生命周期 / View / LifecycleOwner / Jetpack
[文章] Java的自动装箱与自动拆箱
IntegerCache.low)];returnnewInteger(i);}staticfinalintlow=-128;staticfinalinthigh;//可以进行配置,默认是127那么上在这代码可以改成这样,比较方便阅读
[文章] Android学习笔记——记住密码的功能实现(一)
如果没看懂的同学可以通过我在哔哩哔哩分享的视频笔记观看详细步骤,下面附上链接哔哩哔哩视频笔记OK,感谢大家的阅读。本人呢也是刚接触Android,欢迎各路大神提出指导性意见。谢谢啦!
2020-04-12 22:32 · Android
[文章] 不管是不是程序员,英语、数学、计算机一辈子都不能丢
上课我从来不听课,只做一件事情,就是大量阅读文章。不会的单词查一下,读着读着就懂了。所以上学的时候做题目,哪有什么语法分析呀,读过去感觉写什么就写什么。
2020-05-11 00:08 · 英语 / 计算机 / 数学 / 程序员读书 / 杂谈
[问答] 获取文章第一次创建redis文章cache成功 但是在去incr 文章阅读量是报错 获取不到文章
创建的时候可以创建但是获取文章的时候redis自增就报错errvalueisnotaninteroroutofrange百度了没看懂还有redis里面浏览数奇怪目前思路是incr的时候吧1序列化了不要把它序列化存入的时候
2020-12-24 19:26 · java
[文章] Python自动化测试之途牛网机票查询二(完结)
-%d%H:%M:%S",time.localtime()))以下是代码执行的部分截图结语自动化测试文章到此就结束啦(还有部分内容没讲到,比如验证码识别,同学们自己去网上搜索啦),感谢大家的阅读
[文章] Vue服务端渲染技术SSR-数据加载
span>&nbsp;&nbsp;<spanclass="iconfonticon-view"></span><span>阅读次数
2020-01-08 17:42 · nuxt / vue / 前端 / 前后端分离 / 前端开发
[文章] android开发喜马拉雅项目专题篇
demo的代码是开源的,我们可以阅读api的使用方法,另外一个就是可以使用里面的密钥和appID以上这些内容,我们后面配置我们的项目用得上。
  • 1
  • 2