Java 核心语法
01 Java 核心语法这一章解决“Java 代码读写不费力”的基础问题。1. Java 程序基本结构packagecom.example.demo;importjava.util.List;publicclassUserService{privatefinalUserRepositoryrepository;publicUserService(UserRepositoryrepository){this.repositoryrepository;}publicListUserloadUsers(){returnrepository.getUsers();}}必须理解package类的命名空间和目录结构通常对应。import引入其他包里的类不改变类本身归属。public class UserService一个公开类类名通常和文件名一致。字段对象持有的状态。构造器对象创建时初始化依赖。方法对象暴露的行为。Android 中的对应场景Activity、Service、BroadcastReceiver都是类。View.OnClickListener、Runnable是接口。R.java、BuildConfig是构建时生成的类。2. 基本类型和引用类型Java 类型分两大类。类型例子存储含义基本类型int、long、boolean、double、char变量直接表示值引用类型String、User、ListUser、数组变量保存对象引用基本类型类型常用场景注意点byte二进制、协议、文件范围小容易溢出short少见一般不用int计数、索引、状态码默认整数类型long时间戳、数据库 id字面量加Lfloat图形、坐标字面量加fdouble普通小数计算默认浮点类型char单个 UTF-16 code unit不等于完整 Unicode 字符概念boolean条件判断只能是true/false引用类型重点UseranewUser(Tom);Userba;b.setName(Jerry);// a 和 b 指向同一个对象所以 a.getName() 也是 Jerry你必须形成这个直觉引用变量不是对象本身它像一个指向对象的句柄。方法传参时传的是“引用的副本”不是对象副本。3. 装箱和拆箱intcount10;Integerboxedcount;// 自动装箱intrawboxed;// 自动拆箱容易踩坑Integervaluenull;intcountvalue;// NullPointerExceptionAndroid 常见场景Bundle、数据库字段、JSON 解析可能返回包装类型。Integer、Long可以是nullint、long不可以。做 UI 绑定前要明确是否允许空值。建议业务状态必须有值时用基本类型。数据来源可能缺失时用包装类型并在边界处理空值。不要用比较包装对象的值使用equals或拆成基本类型。4. 类型转换longa100;// int 自动提升为 longintb(int)a;// long 转 int 需要强转强转不是“安全转换”只是告诉编译器允许转换运行时仍可能出错或丢数据。Objectobjhello;Stringtext(String)obj;// 可以Objectvalue123;Stringwrong(String)value;// ClassCastException安全写法if(objinstanceofString){Stringtext(String)obj;}Android 常见场景findViewById返回具体 View 类型时可能需要转换。Intentextra、Bundle、RecyclerView.ViewHolder都经常涉及类型边界。反射、系统服务、AIDL 返回值更要检查类型。5. 字符串String是不可变对象。Stringsa;ssb;这里不是把原对象改成ab而是创建了新字符串并让s指向新对象。常见规则内容比较用equals。常量在左侧可避免 NPEok.equals(status)。大量拼接用StringBuilder。日志拼接在高频路径要注意额外对象创建。StringBuilderbuildernewStringBuilder();for(Stringitem:items){builder.append(item).append(,);}Stringresultbuilder.toString();Android 常见场景UI 文案用资源不要硬编码。多语言不要用字符串拼接句子优先使用格式化资源。日志里不要打印隐私字段、token、手机号完整值。6. 数组int[]numbersnewint[3];numbers[0]10;String[]names{Tom,Jerry};特点长度固定。可以按索引快速访问。越界会抛ArrayIndexOutOfBoundsException。数组是对象。数组和集合选择需求选择固定长度、性能敏感、基础数据数组长度变化、增删多、业务列表List唯一性Setkey-value 查询MapAndroid 中业务层一般优先用集合底层图像、音频、协议、Parcel、数据库游标处理时数组更多。7. 控制流if(isLogin){showHome();}else{showLogin();}switch(status){case0:showLoading();break;case1:showContent();break;default:showError();break;}注意Java 传统switch需要break否则会继续执行后面的 case。条件复杂时优先提取成有名字的方法。状态多时考虑 enum、状态对象或策略模式避免巨型if/else。8. 方法和参数传递publicvoidrename(Useruser){user.setName(Tom);}publicvoidreplace(Useruser){usernewUser(Jerry);}Java 只有值传递。引用类型传递的是引用值的副本。rename修改的是同一个对象的内部状态外部能看到变化。replace只是让方法内部的局部变量指向新对象外部引用不变。这个点非常重要很多 Android bug 来自“以为传进去会替换外部对象”。9. 重载voidlog(Stringmessage){}voidlog(Stringtag,Stringmessage){}voidlog(Throwableerror){}重载由参数列表决定不由返回值决定。intgetValue(){return1;}// String getValue() { return 1; } // 只改返回值不能构成重载建议重载过多会降低可读性。参数含义相近但业务差异大时使用不同方法名。多个 boolean 参数是坏味道容易调用错。10. 构造器和初始化顺序publicclassUser{privatefinalStringname;publicUser(Stringname){this.namename;}}初始化顺序简化记忆父类静态字段/静态代码块子类静态字段/静态代码块父类实例字段/实例代码块父类构造器子类实例字段/实例代码块子类构造器Android 场景Activity不要在构造器里做业务初始化生命周期还没开始。依赖Context的初始化通常放在onCreate或注入框架里。静态初始化不要做重 IO、反射扫描、数据库打开容易拖慢启动。11.staticstatic属于类不属于某个对象。publicclassConstants{publicstaticfinalintMAX_COUNT100;}常见用途常量工具方法静态工厂方法单例持有者Android 风险publicclassBadStore{publicstaticActivitycurrentActivity;}静态字段持有Activity很容易内存泄漏。Activity生命周期结束后如果还有静态引用指向它GC 无法回收。12.finalfinal可以修饰变量、方法、类。finalintcount1;// 不能重新赋值finalListStringlistitems;// 引用不能换但 list 内容仍可变publicfinalclassImmutableUser{privatefinalStringname;}理解重点final修饰引用不等于对象不可变。真正不可变对象需要字段私有、构造后不变、不暴露可变内部对象。并发场景下不可变对象更容易保证线程安全。13. 访问控制修饰符同类同包子类任意位置privateyesnononopackage-privateyesyesnonoprotectedyesyesyesnopublicyesyesyesyes没有写修饰符就是 package-private。建议默认尽量小权限。字段优先private。对外暴露稳定方法不直接暴露可变字段。Android module 边界清晰时包可见能力很好用。14. 注解常见注解OverridepublicStringtoString(){returnUser;}Android 常见注解NonNull、NullableMainThread、WorkerThreadUiThreadIntDef、StringDefSuppressWarnings注解本身不一定改变运行行为但可以帮助编译器、lint、IDE、框架做检查或生成代码。15. 本章自测int和Integer的区别是什么什么时候会发生 NPEString a x; a y;是否修改了原字符串Java 方法传对象时是值传递还是引用传递static final ListString是否表示列表内容不可变private、默认访问、protected、public的边界是什么为什么 Android 中不建议静态持有Activity和equals分别比较什么数组和List的核心差异是什么