@JvmField val TAGS = WeixinHook.TAG + ".Test" const val TAGSG = WeixinHook.TAG + ".Test" @NotNull @JvmField public static final String TAGS = "hotB.wechat.Test"; @NotNull public static final String TAGSG = "hotB.wechat.Test";
在class中
1 2 3 4 5 6 7 8 9
private const val TAG = XLog.hotPanel + "DeviceUtil" class DeviceUtil{}
生成了另一个文件存储const public final class DeviceUtilKt { /* renamed from: MB */ private static final long f14MB = 1048576; private static final String TAG = "hotPanel.DeviceUtil"; }
companion object { private const val MSG_UPDATE_PROGRESS = 1 private const val MSG_UPDATE_TIME= 1000 }
静态内部类
1 2 3 4 5 6 7
class Parent{ class Child //默认就是 java的 public static } fun main(args: Array<String>) { val inner = Parent.Child() }
非静态内部类
1 2 3 4 5 6 7
class Parent{ //非静态内部类声明 inner class Child } fun main(args: Array<String>) { val inner = Parent().Child() }
内部类访问外部持有类的this
1 2 3 4 5 6 7 8 9 10 11 12 13
class Parent{ val a:Int = 0 inner class Child{ val a:Int = 5 fun hello(){ println(this@Parent.a) } } } fun main(args: Array<String>) { val inner = Parent().Child() inner.hello() }
三元运算符
1 2 3 4
//Java写法 int size=list!=null?list.size:0 //kotlin写法 val size=if(list!=null) list.size() else 0
switch (NetUtils.INSTANCE.providerType(WxVersions.CURRENT_APPLICATION)) { case NetUtils.PROVIDER_TYPE_MOVE: destinationAddress = NetUtils.INSTANCE.getNET_TYPE_MOVE(); break; case NetUtils.PROVIDER_TYPE_UNICOM: destinationAddress = NetUtils.INSTANCE.getNET_TYPE_UNICOM(); break; case NetUtils.PROVIDER_TYPE_TELECOM: destinationAddress = NetUtils.INSTANCE.getNET_TYPE_TELECOM(); break; default: destinationAddress = null; break; }
反编译后的NetUtils
1 2 3 4 5 6 7 8 9 10 11 12 13 14
public final class NetUtils { public static final NetUtils INSTANCE = new NetUtils(); @NotNull private static final String NET_TYPE_MOVE = NET_TYPE_MOVE; @NotNull private static final String NET_TYPE_TELECOM = NET_TYPE_TELECOM; @NotNull private static final String NET_TYPE_UNICOM = NET_TYPE_UNICOM; public static final int PROVIDER_TYPE_MOVE = 1; public static final int PROVIDER_TYPE_TELECOM = 3; public static final int PROVIDER_TYPE_UNICOM = 2;
class MicroMsg { companion object { val DB_NAME = "EnMicroMsg.db" } } 而下面这样写法拿不到DB_NAME class MicroMsg { val DB_NAME = "EnMicroMsg.db" companion object { } }
伴生对象如何生成public static final
1 2 3 4 5 6 7 8 9 10 11
class MicroMsg { companion object { val TYPE_IMG = 1 val TYPE_FILE = 2 const val TYPE_VOICE = 3 } } 反编译后 private static final int TYPE_FILE = 2; private static final int TYPE_IMG = 1; public static final int TYPE_VOICE = 3;
constructor构造器
1 2 3 4 5 6 7 8 9 10 11 12 13
1.主构造器 class MultiTask<TaskData, Result> constructor(private val mTaskItem: TaskItem, private val mRequest: TaskData, private val mTaskCount: Int, private val mDelay: Long = 500)
2.主构造器可以省略constructor class MultiTask<TaskData, Result> (private val mTaskItem: TaskItem, private val mRequest: TaskData, private val mTaskCount: Int, private val mDelay: Long = 500)
3.主构造器如果有@JvmOverloads则不可以省略constructor class MultiTask<TaskData, Result> @JvmOverloads constructor(private val mTaskItem: TaskItem, private val mRequest: TaskData, private val mTaskCount: Int, private val mDelay: Long = 500)
4.使用@JvmOverloads注解的主构造器,不可以再有次构造器 constructor(taskItem: TaskItem,mRequest: TaskData,mTaskCount: Int): this(taskItem, mRequest,mTaskCount,300) { } 异常,hava the same JVM signature.
私有构造器 class OuterConstructor private constructor(str:String, ins:Int){}
私有构造器+次构造器(可调) class OuterConstructor private constructor(str:String, ins:Int){ var s1 = "123" init{ this.s1 = str } constructor(str:String):this(str,8) } 主构造器 class OuterConstructor constructor(str:String, ins:Int){ var s1 = "123" init{ this.s1 = str } constructor(str:String):this(str,8) }
主构造器省略初始化init class OuterConstructor { var s1 = "123" init{ this.s1 = "qdf" } } 主构造器初始化init class OuterConstructor constructor(str:String, ins:Int){ var s1 = "123" init{ this.s1 = str } }
@JvmOverloads作用
在有默认参数值的方法中使用@JvmOverloads注解,则Kotlin就会暴露多个重载方法。
1 2 3 4 5 6
@JvmOverloads fun f(a: String, b: Int=0, c:String="abc"){ } 反编译后: void f(String a) void f(String a, int b) void f(String a, int b, String c)
所以@JvmOverloads不仅仅用于构造方法。
constructor中参数指定val,var和没有制定的区别
不指定
1 2 3
class OuterConstructor constructor(mHookConfig: HookConfig) 反编译后 public AvatarServiceImplKT(@NotNull HookConfig mHookConfig) {}
val
1 2 3 4
class OuterConstructor constructor(val mHookConfig: HookConfig) 反编译后 private final HookConfig mHookConfig; public AvatarServiceImplKT(@NotNull HookConfig mHookConfig) {}
var
1 2 3 4
class OuterConstructor constructor(var mHookConfig: HookConfig) 反编译后 private HookConfig mHookConfig; public AvatarServiceImplKT(@NotNull HookConfig mHookConfig) {}
vararg可变参数
1 2 3 4 5 6 7 8 9
fun print(vararg msgs: String) { for (msg in msgs) { println(msg) } }
fun LogPrinters(){ print("11","22","33","44"); }
但是如果是下面这样调用是不可以的,会报参数匹配异常:
1 2
val array = arrayOf("a", "b", "c", "d") print(array)
for (index in 10 downTo 1){ print(index)//会输出10..1 }
想不使用1作为遍历的步长,可以使用step()函数:
1 2 3
for (index in 1..100 step 2){ print(index)//会输出1..3..5...... }
要创建一个不包含末尾元素的区间:
1 2 3
for (index in 1 until 10){ println(index)//输出1..9 }
遍历一个数组/列表,想同时取出下标和元素:
1 2 3 4 5 6 7
val array = arrayOf("a", "b", "c") for ((index,e) in array.withIndex()){ println("下标=$index----元素=$e") } [-----index:][main]下标=0----元素=a [-----index:][main]下标=1----元素=b [-----index:][main]下标=2----元素=c
遍历一个数组/列表,只取出下标:
1 2 3 4
val array = arrayOf("a", "b", "c") for (index in array.indices){ println("index=$index")//输出0,1,2 }
遍历取元素:
1 2 3 4
val array = arrayOf("a", "b", "c") for (element in array){ println("element=$element")//输出a,b,c }
public static <T> void copy(List<? super T> dest, List<? extends T> src) { // 校验略 ListIterator<? super T> di = dest.listIterator(); ListIterator<? extends T> si = src.listIterator(); while (si.hasNext()) { /** * 编译时异常 * Incompatible types.不兼容类型; * Required:T; * Found:Capture<? super T> */ T elementD =di.next();
T element = si.next(); //src extent 生产者 作为方法返回值类型是安全的 di.set(element); // dest super 消费者 作为方法参数类型是安全的
/** * 编译时异常 * set(<? extends T>) in ListIterator cannot be applied. * to (T) */ si.set(elementD); } }
kotlin:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
abstract class Supplier<out T> { abstract fun get(): T /** * 编译期错误: * Type parameter T is declared as 'out' but occurs in 'in' position in type T */ abstract fun set(t: T) }
abstract class Customer<in T> { abstract fun set(t: T) /** * 编译期错误: * Type parameter T is declared as 'in' but occurs in 'out' position in type T */ abstract fun get(): T }
1.List<? extends T>协变:== out
在si.set(elementD)中, elementD的类型是T,所以我们可以set(T t),以及一切参数中含有 T 的方法(称为消费者方法),T类型或者从T继承的类型都可以被set,但是因为可以set不同的类型,所以这些方法可能会破坏类型安全,所以编译器限制这些方法的调用。
举kotlin例说明: 有一方法
1 2 3
fun generate(args : Array<Any>){ //todo }
我们调用它:
1 2
val args : Array<String> = arrayOf() generate(args)
val map = XXXXX ?: return 等同于 val map = XXXXX if(map == null){ return } 但是if会有://Replace 'if' with elvis operator
toString()
1 2 3 4 5
/** * Returns a string representation of the object. Can be called with a null receiver, in which case * it returns the string "null". */ public fun Any?.toString(): String
疑问点: null.toString() 反编译 String.valueOf(null)
Serializable
1
class XXXXKT:Serializable{}
Cannot access ‘Serializable’:it is internal in ‘kotlin.io’
解决:import java.io.Serializable
@Suppress(“UNCHECKED_CAST”)
当使用 as Array强转时可能会出现Unchecked cast: Any! to Array 警告。解决方法就是在强转代码前加@Suppress(“UNCHECKED_CAST”)。 备注:@SuppressWarnings(“unchecked”)使用时机呢?