开发小知识、问题(持续更新)

开发小知识、问题(持续更新)

lucas Lv4

1. AS apk 安装包安装位置

2022.3.1版本

/app/build/intermediates/

/app/build/outputs/apk/debug/app-debug.apk

2. AS R 文件位置

2022.3.1版本

R.png

/app/build/intermediates/runtime_symbol_list/debug/R.txt

3. AS OpenGL ES 相关库文件在什么位置

2022.3.1版本

ndk 目录里面,MacOS/Users/yourUserName/Library/Android/sdk/ndk/

4. Android 开发 OpenGL ES 找不到 GL_TEXTURE_BORDER_COLOR

GLES3/gl3.h 里面没有,在 GLES3/gl32.h

5. AS 写 C++ 的时候,一直提示当前文件不属于任何项目

2022.3.1版本

如果你确定你已经将文件添加到 CMakeList.txt 里面,但依旧没作用

那大概率是下面的问题

This file is not part of the project. Please include it in the appropriate build file (build.gradle, CMakeLists.txt or Android.mk etc.) and sync the project.

这是因为 CMake 没有重新加载,你可以 Sync Project with Gradle Files ,就是这个图标

Sync Project with Gradle Files.png

如果没有效果,那大概是直接用了缓存,没有重新加载

你可以在 CMakeList.txt 里写几行 message ,直到右上角出现 Sync Project

External build files have changed since last project sync. A project sync may be necessary for the IDE to work properly.

6. AS C++ 没有代码提示,并且代码高亮多处爆红

2022.3.1版本

这是因为 Android Studio 在你没有 #include .h文件 或者没有调用某个 C++ 函数的时候,是不给你进行代码检查的

我还专门跟 Google 发了邮件,得到了如上回复

7. MacOS 删除 .DS_Store

1
find /Users/username/dir/ -name ".DS_Store" -exec rm {} \;

/Users/username/dir/ 这是你想删除 .DS_Store 的文件夹

8. jni 中,类型映射

写这个的主要原因是因为 Kotlin 类型需要对应到 Java 包名才可以

基本类型(Primitive Type)

Java 类型 Kotlin 类型 Native 类型 描述 符号
int Int jint 有符号32位整型(int) I
short Short jshort 有符号16位整型(short) S
long Long jlong 有符号64位整型(long) J
float Float jfloat 32位浮点型(float) F
double Double jdouble 64位浮点型(double) D
boolean Boolean Jboolean 无符号8位整型(unsigned char) Z
char Char Jchar 无符号16位整型(unsigned short) C
byte Byte jbyte 有符号8位整型(char) B

引用类型(Reference Type)

Java 类型 Kotlin 类型 Native 类型 描述 符号
Class Class jclass Class类对象 Ljava.lang.Class;
Object Any jobject - Ljava.lang.Object;
String String jstring - Ljava/lang/String;
Object[] AnyArray jobjectArray - [Ljava.lang.Object;
boolean[] BooleanArray jbooleanArray - [Z
byte[] ByteArray jbyteArray - [B
char[] CharArray jcharArray - [C
short[] ShortArray jshortArray - [S
int[] IntArray jintArray - [I
long[] LongArray jlongArray - [J
float[] FloatArray jfloatArray - [F
double[] DoubleArray jdoubleArray - [D
void Unit Void - V

除了基本数据类型,以及 void ,基本都是 L+包名+; ,数组再在开头加一个 [

9. Windows 的狗屎快捷键 🖕🖕🖕💩💩💩

总有一些“才智冠绝”、“谦虚谨慎”的人,提出让大众“赞不绝口”的设计需求

使用频率低,还无法更改的快捷键就是一种(他甚至连关闭都不让!!!)

ctrl + 空格切换中英文、win + → 改窗口位置……

这些无法更改的快捷键对于一个使用大量快捷键的程序猿简直就是噩梦

10. 什么是内存泄漏

  • 内存泄漏是指“逻辑”上某个实例无用了,但是仍旧没有回收
  • 并不能用是否持有引用来进行判断
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class MemoryLeak {
public static void main(String[] args) {
Person p = new Person();
Name n = new Name();
p.name = n;
n = null;

}
}

class Person {
Name name;
}

class Name {
String firstName;
String SecondName;
}

这里 n = null 但是 p 依旧持有 n 的引用,这不一定是内存泄漏,只是对 n 主动丢弃了一个引用,有可能后面还是要使用这个n

11. mac 常用命令

  1. 清除 app 的扩展属性

    1
    sudo xattr -cr

    -c:表示 清除(clear)文件的所有扩展属性。
    -r:表示 递归(recursive),即对目录下的所有子文件和子目录也执行相同操作。

    当然还有其他操作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    $ xattr -h
    用法:xattr [-l] [-r] [-s] [-v] [-x] 文件 [文件 ...]
    xattr -p [-l] [-r] [-s] [-v] [-x] 属性名称 文件 [文件 ...]
    xattr -w [-r] [-s] [-x] 属性名称 属性值 文件 [文件 ...]
    xattr -d [-r] [-s] 属性名称 文件 [文件 ...]
    xattr -c [-r] [-s] 文件 [文件 ...]

    第一种形式列出给定文件上所有 xattr 的名称。
    第二种形式 (-p) 打印 xattr 属性名称的值。
    第三种形式 (-w) 将 xattr 属性名称的值设置为字符串 attr_value。
    第四种形式 (-d) 删除 xattr 属性名称。
    第五种格式 (-c) 删除(清除)所有扩展属性。

    选项:
    -h:打印此帮助
    -l:打印长格式(属性名称:属性值,十六进制输出包含偏移量和
    ASCII 表示)
    -r:递归执行
    -s:对符号链接本身执行操作,而不是链接指向的内容
    -v:同时打印文件名(使用 -r 选项并处理多个文件时自动执行)
    -x:将属性值表示为十六进制字符串,用于输入和输出

    扩展属性是 Mac 给 app 添加的元数据,比如:

    • com.apple.quarantine :表示文件是从网上下载的,macOS 会限制运行并弹出“来自不明开发者”的提示。
    • com.apple.metadata:kMDItemWhereFroms :文件的来源网址或路径,用于 Finder “显示简介”中显示“从何处下载”。
    • com.apple.ResourceFork :存储老式 Mac 资源分支的数据(已较少使用)。
    • com.apple.FinderInfo :用于 Finder 显示图标、标签等信息。
    • com.apple.metadata:_kMDItemUserTags :Finder 标签(颜色标签等)信息。
    • com.apple.metadata:kMDItemDownloadedDate :下载日期。
    • com.apple.TextEncoding :文件的文本编码信息(如 UTF-8)。
    • com.apple.backup.SnapshotVolumeUUID :Time Machine 快照相关信息。
    • com.apple.provenance :App 安装源标识(如 App Store)。
    • com.apple.lastuseddate#PS :最近使用日期,Spotlight 使用的。

    如果在使用 Time Machine 就要谨慎使用这个命令,这可能会让你的存储信息损坏

  2. 打开所有 app 安装来源

    1
    sudo spctl --master-disable

12. JvmPlatformAnnotations.kt

image-20250505212602199

@JvmOverloads

在 Kotlin 中支持默认参数,写了默认参数的函数在调用的时候可以不写有默认值参数,但 Java 不支持。

这个注解会为具有默认参数的函数生成多个重载方法,使 Java 调用时达到和 kotlin 类似的效果。

1
2
3
4
5
class JvmPlatformAnnotationsDemo {
@JvmOverloads
fun testOverLoad(a: Int = 0, b: String = "s", c: Double, d: Float = 0f, e: Long = 0) {
}
}

这里有 5 个参数,其中就 c 是没有默认值的,所以编译器应该考虑所有的有默认值的参数不被写的情况,但实际呢?

反编译成 java :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public final class JvmPlatformAnnotationsDemo {
@JvmOverloads
public final void testOverLoad(int a, @NotNull String b, double c, float d, long e) {
Intrinsics.checkNotNullParameter(b, "b");
}

// $FF: synthetic method
public static void testOverLoad$default(JvmPlatformAnnotationsDemo var0, int var1, String var2, double var3, float var5, long var6, int var8, Object var9) {
if ((var8 & 1) != 0) {
var1 = 0;
}

if ((var8 & 2) != 0) {
var2 = "s";
}

if ((var8 & 8) != 0) {
var5 = 0.0F;
}

if ((var8 & 16) != 0) {
var6 = 0L;
}

var0.testOverLoad(var1, var2, var3, var5, var6);
}

@JvmOverloads
public final void testOverLoad(int a, @NotNull String b, double c, float d) {
Intrinsics.checkNotNullParameter(b, "b");
testOverLoad$default(this, a, b, c, d, 0L, 16, (Object)null);
}

@JvmOverloads
public final void testOverLoad(int a, @NotNull String b, double c) {
Intrinsics.checkNotNullParameter(b, "b");
testOverLoad$default(this, a, b, c, 0.0F, 0L, 24, (Object)null);
}

@JvmOverloads
public final void testOverLoad(int a, double c) {
testOverLoad$default(this, a, (String)null, c, 0.0F, 0L, 26, (Object)null);
}

@JvmOverloads
public final void testOverLoad(double c) {
testOverLoad$default(this, 0, (String)null, c, 0.0F, 0L, 27, (Object)null);
}
}

可以看到,编译器并是不排列组合生成重载,也就是说,如果你的 kotlin 这么调用:

1
JvmPlatformAnnotationsDemo().testOverLoad(b = "sss", c = 3.14)

java 是没法调用的,java 只能调用 public final void testOverLoad(int a, @NotNull String b, double c) 方法

这是为啥啊?大概就是防止指数级膨胀

@JvmStatic

用于将 Kotlin 的对象(object)或伴生对象中的方法标记为静态方法(static)供 Java 调用。

1
2
3
4
object Utils {
@JvmStatic
fun foo() {}
}
1
Utils.foo();

@JvmName

用于更改 Kotlin 生成的 Java 方法或类的名字。

1
2
3
@file:JvmName("MyKt")
@JvmName("addInt")
fun add(a: Int, b: Int): Int = a + b
1
int result = MyKt.addInt(1, 2);

@JvmMultifileClass

用于将多个 Kotlin 文件合并为一个 Java 类(通常用于多个 file 声明中带 @file:JvmName("..."))。

1
2
@file:JvmName("Utils")
@file:JvmMultifileClass

多个文件的顶层函数会被合并到一个 Java 类中。

@JvmPackageName

指定生成的 Java 类的包名,避免 Kotlin 的文件在默认包中生成 Java 类。

1
@file:JvmPackageName("com.example.utils")

@JvmSynthetic

该方法或属性对 Java 是不可见的,但在 Kotlin 中可用。常用于隐藏不安全的 API 或内部实现。

@Throws

声明 Kotlin 函数会抛出哪些异常,让 Java 可以正确捕获异常。

1
2
3
4
@Throws(IOException::class)
fun readFile() {
throw IOException("Failed")
}

@ImplicitlyActualizedByJvmDeclaration

用于 expect/actual 多平台支持。这个注解通常由编译器自动处理,用于实际实现是 JVM 上的 API。

@JvmField

使属性在 Java 中可直接访问为字段,避免生成 getter/setter。

1
2
3
4
class MyClass {
@JvmField
val id = 1
}

Java 中可以直接 myClass.id,否则需要调用 getId()

@JvmSuppressWildcards

抑制泛型类型中通配符的自动生成,常用于与 Java 泛型协作。

1
fun acceptList(@JvmSuppressWildcards list: List<Any>)

@JvmWildcard

@JvmSuppressWildcards 相对,强制某个类型参数生成通配符。

1
fun provide(): List<@JvmWildcard String>

@JvmInline

用于定义内联类(value class),它会在字节码中作为原始类型使用以提高性能。

1
2
@JvmInline
value class UserId(val id: String)

@JvmRecord

用于标记 Kotlin 的数据类为 Java 16+ 的 record 类型,需配合 JVM target 17。

1
2
@JvmRecord
data class Point(val x: Int, val y: Int)

13. IDEA 快捷键(适用 Android Studio)

1. 检索当前文件的变量和函数(File Structure):cmd + F12

2. 参数信息(Parameter Info):cmd + P

  • Title: 开发小知识、问题(持续更新)
  • Author: lucas
  • Created at : 2023-04-23 22:30:58
  • Updated at : 2025-05-13 23:47:27
  • Link: https://darkflamemasterdev.github.io/2023/04/23/开发小知识、问题(持续更新)/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments