
这一篇是“Java语言Android前篇”系列的第十三篇。能走到这里的读者说明前面的基础语法、流程控制、数组、面向对象这些内容已经过了一遍不再是完全零基础的状态。但我也很清楚很多人学到这个阶段心里反而发虚Java语法学了类和对象也背得滚瓜烂熟可一想到“接下来要学Android”还是不知道Java在Android里到底是怎么用的。这篇没有全新的大块知识点重点是“把已经学过的东西串起来”用Android开发的实际场景反推Java核心知识同时把环境配置、排序算法、常用库函数、数据库连接、文件路径这几块程序员日常绕不开的内容补全。适合三类人看打算转Android的Java初学者、准备Java面试但基础不够牢的同学、以及看了很多语法书但没写过像样程序的自学者。1. 项目概述与系列定位1.1 系列走到这里解决了什么问题从系列第一篇开始我一直坚持一个观点学Java一定不能“为学而学”每个知识点必须知道它将来用在哪。前十二篇我们做的事情可以概括成三个阶段第一阶段搭好开发环境把JDK、IDE这些工具链理清楚第二阶段过完语言基础变量、运算符、分支循环、数组这些是写任何程序的地基第三阶段进入面向对象类、继承、接口、异常处理这部分是Java的灵魂也是Android里Activity、Fragment这些组件能灵活运转的底层逻辑。到了第十三篇课程节奏需要做一个调整。如果继续往下灌新语法比如泛型嵌套、反射、注解的底层原理大部分初学者反而会被绕晕。这个阶段的真实需求是把已经学过的知识点做一次系统性回炉再补上几块“平时不太起眼、但真干活时一定会碰到”的内容。比如环境变量配置错了怎么排查比如冒泡排序这种基础算法能不能手写出来比如Java程序连数据库时那些版本兼容的老问题。这些内容在教科书里往往是散落的但在实际开发中都是绕不开的硬功夫。1.2 为什么第十三篇要做“回炉”而不是“上新”我见过太多人犯同一个错误Java语法书翻了一遍ArrayList、HashMap都会用但一打开Android Studio就傻眼因为Android里的Java不是“写一段main方法然后跑出结果”而是要和Activity生命周期、UI布局、异步任务这些东西纠缠在一起。同样一个List在纯Java里你可能只是打印集合元素在Android里你要把它塞进RecyclerView的Adapter还要处理数据更新后的界面刷新。所以这一篇的定位不是“讲新知识”而是“建立连接”。我会反复做一个动作拿Android里最常见的场景回头去解释Java里那个知识点当初为什么这样设计。比如回调接口为什么在Java里用接口而不是普通类因为Android里按钮点击、网络请求结果、列表项点击全靠回调比如异常处理为什么强调“捕获后要处理”因为Android App崩溃直接表现为“应用已停止运行”体验非常恶劣。当你用这种方式重新看待Java理解深度会明显不一样。2. 开发环境是第一个拦路虎2.1 JDK的安装与配置从本机到老服务器的兼容性处理环境配置这个环节零基础的人往往觉得“不就是下一步下一步吗”但它恰恰是问题最多的地方。你在搜索引擎里输入“java 环境配置”能看到大量五花八门的问题我挑几个最高频的来说。先说最核心的JAVA_HOME和PATH。JAVA_HOME这个环境变量指向JDK安装目录PATH里要添加%JAVA_HOME%\bin。为什么一定用JAVA_HOME这种中间变量而不是直接把路径写进PATH因为很多基于Java的中间件Tomcat、Maven、Gradle都要自己读取JAVA_HOME去找JDK如果你只配了PATH没配JAVA_HOME本机运行java -version没问题但一跑Gradle就报错找不到JDK。这是新手最常见的隐形坑。然后是老服务器的问题。热搜词里有一条“2012服务器jdk怎么配置java”这其实是Windows Server 2012 R2上装JDK的场景。这类老系统有几个通病系统本身可能没有图形化的“高级系统设置”入口或者PATH变量被系统搞得很长你编辑的时候手一抖就把原有路径删了。我的建议是用setx命令来做而不是走图形界面setx JAVA_HOME C:\Program Files\Java\jdk-17 /M setx PATH %PATH%;%JAVA_HOME%\bin /M注意setx会自动把内容写进注册表里的用户环境变量但新的环境变量不会立刻对当前打开的CMD窗口生效需要重开一个终端。另外/M参数表示修改系统级环境变量需要管理员权限。我实际测试过老服务器上这个方法最稳妥比手动画界面快得多。还有一个细节老的32位系统JDK版本不能装太高JDK 8是最后的32位支持版本到了JDK 11就只能装64位了。你要是给2012服务器配JDK先看清楚系统是32位还是64位否则装完一堆莫名其妙的报错。2.2 Android Studio的中文化与初始化很多人拿到Android Studio第一件事就是问“怎么设置成中文”。新版Android Studio2023年以后版本其实已经内置了中文语言包在Settings里搜索“language”就能切换不需要额外装插件。如果你用的是老版本需要去插件市场下载“Chinese Language Pack”插件装完重启同样能变中文。不过我建议别在这上面花太多精力Android Studio的英文界面单词量非常有限Settings、Project、Debug这些词看两遍就熟了把肌肉记忆留到真正的编程上更有价值。初始化阶段真正的坑是Gradle下载。Android Studio创建项目后会通过网络拉取Gradle和依赖库国内网络环境下拉一两个小时是家常便饭。我常用的处理方式是在项目的gradle-wrapper.properties文件里手动指定一个能访问的Gradle版本下载地址或者提前用其他渠道下载好Gradle压缩包解压到C:\Users\用户名\.gradle\wrapper\dists对应的目录下。这样再启动项目就能跳过最耗时的下载步骤。2.3 Java启动失败的典型场景与排查思路“java启动失败怎么解决”这个搜索词背后对应的场景其实五花八门。有GUI程序弹窗说Failed to create JVM的有命令行里敲java显示找不到命令的还有服务端项目启动时端口被占用的。我把排查思路统一成一条线第一步先确认基础环境。执行java -version能正常输出版本号说明JDK基本没问题再执行echo %JAVA_HOME%看环境变量有没有指向正确的安装目录。这两个命令都不报错再往后排查。第二步区分是编译问题还是运行问题。如果是javac编译报错多半是代码里的语法或依赖问题如果是运行java命令报错就要看是不是缺少相关的JAR包或者classpath没配好。这里有个常见误解很多人以为Java是“纯解释执行”的其实Java是先编译成字节码.class文件再由JVM通过解释器或JIT编译器执行。所以同一套代码在不同机器上表现不一致绝大多数是JVM版本差异导致的。第三步看报错信息定位具体原因。比如“端口被占用”的报错信息里会包含java.net.BindException你只要在命令行执行netstat -ano | findstr 端口号找到占用进程的PID然后在任务管理器里结束它就行。再比如“Could not reserve enough space for object heap”这是JVM内存参数设置过大检查启动脚本里的-Xmx参数把它调小到本机物理内存能承受的范围。3. Java核心语法用Android的视角再学一遍3.1 面向对象不是背概念而是看Android里的影子面向对象这块如果只会背“封装、继承、多态”的定义那面试和实际开发是两码事。我换一个讲法直接给你看Android里到处都在用的面向对象。你打开任意一个Android项目的源码随便点开一个Activity第一行一定是public class MainActivity extends AppCompatActivity。这个extends就是继承。AppCompatActivity是所有兼容式Activity的基类里面封装了生命周期管理、主题适配、权限兼容这些底层逻辑你的MainActivity只需要继承它就能免费获得这些能力。你如果再点开AppCompatActivity的源码看会发现它又继承了FragmentActivity再往上追溯到ComponentActivity、Activity。这一条继承链就是Java继承机制的教科书级演示。再看接口。你在Android里给按钮设置点击事件最常见写法是findViewById(R.id.btn_submit).setOnClickListener(new View.OnClickListener() { Override public void onClick(View v) { // 处理点击逻辑 } });这里的View.OnClickListener就是接口。为什么用接口而不用普通类因为接口只定义“你有onClick这个行为”但不关心这个行为具体怎么实现。同一个按钮可以被各种不同的ClickListener实现不同的逻辑界面只负责调用接口方法。这就是“面向接口编程”的意义——调用方和被调用方解耦。多态在Android里的典型例子是Adapter。你写一个RecyclerView.Adapter的子类重写onCreateViewHolder、onBindViewHolder这些方法RecyclerView框架会在合适的时机调用它们但框架本身根本不知道你的适配器里具体做了什么。框架调用的是父类定义的抽象方法实际跑的是子类实现这就是动态绑定。理解了这一层你再回头看Java多态会发现自己之前只是应付考试现在才是真正理解。3.2 集合与泛型从ArrayList到列表数据的基础集合框架是Java里最常用的工具库没有之一。Android开发里你几乎不可能不用集合接口返回的数据列表、本地缓存的数据、用户选择的多个选项都是集合的典型场景。ArrayList是最基础的底层就是一个Object数组可以动态扩容适合随机访问。LinkedList底层是双向链表适合频繁插入删除。HashMap底层是哈希表通过key直接定位value查询效率接近O(1)。我在给初学者讲的时候会打一个比方ArrayList像一本按页编号的书你要读第100页翻过去就能读LinkedList像一条铁链每节都连着前后要取中间某一节得从头往后摸HashMap像一本字典你按拼音首字母翻到那一页直接找字不用一页页翻。泛型是集合里最容易忽略但最重要的部分。你写ListString意思是这个集合里只能放String对象取出来的时候自动就是String类型不需要强转。如果不用泛型写List取出来的元素全是Object用之前必须(String) list.get(0)手动强转稍有不慎就ClassCastException。在Android里泛型用得最频繁的地方就是Adapter的声明public class MyAdapter extends RecyclerView.AdapterMyAdapter.ViewHolder这个尖括号里的类型是你在实体层就定死的编译器帮你做类型检查运行期少了一堆麻烦。3.3 异常处理捕获与抛出Android崩溃的防火墙Java异常处理的核心结构无非是try-catch-finally和throws、throw真正考验人的是“什么时候该捕获什么时候该抛出捕获之后该怎么处理”。这个判断标准在Android里会直接影响App的稳定性。先说最常见的落地场景网络请求。Android里访问网络时经常需要处理IOException、SocketTimeoutException这些受检异常编译器强制你用try-catch包裹或者throws声明。如果你用throws一路往外抛最后抛到Activity的某个回调里没人接程序直接崩溃。正确的做法是在最上层做一个“兜底”捕获弹一个Toast告诉用户“网络不给力请稍后重试”然后把异常日志打出去方便排查。异常处理的目的从来不是“吃掉错误”而是“在错误发生时让程序体面地降级”。还有一个我踩过的坑finally里不要做返回或抛出异常。静态代码检查工具经常警告Dont return inside a finally block原因很简单finally块会在任何情况下执行如果在这里return会覆盖掉try里的正常返回值。我写过一版文件上传的代码try里已经返回成功标志finally里误加了一句清理操作结果清理方法抛了NullPointerException把原来的成功结果整个冲掉了排查了很久才发现。3.4 多线程入门为Android异步任务提前预热Android应用的主线程也叫UI线程所有界面操作必须在主线程执行但耗时的网络请求和文件读写不能卡在主线程否则用户会看到界面假死系统甚至会弹“应用无响应”对话框。所以多线程是Android开发绕不开的基石。Java多线程最简单的人手方式是Thread和Runnable。启动一个线程就是new Thread(() - { // 耗时任务 }).start()。但直接用Thread有两个问题线程的创建和销毁开销大频繁操作会浪费性能如果一个应用的并发任务多每个任务都开一个线程机器再强也扛不住。所以实际开发中会用线程池ExecutorService来复用线程这个设计思想我在Android里反倒见得更多比如Gradle构建时的并行任务、RxJava的调度器底层都是线程池。线程安全这块我建议至少掌握两个点synchronized关键字和volatile关键字。synchronized用来给代码块或方法加锁保证同一时刻只有一个线程进入临界区volatile用来修饰变量保证线程之间对该变量的修改是可见的。Android里的Handler机制也跟多线程密切相关子线程做完耗时任务要通过Handler把消息发回主线程更新UI。虽然现在很多新项目直接用Kotlin协程但协程底层依然依赖线程调度理解Java多线程再做协程心智负担会小很多。4. 基础算法与常用库面试笔试不丢分4.1 手写冒泡排序的完整推演“冒泡排序java”排在热搜词里一点都不意外因为它是面试笔试里最高频的算法题没有之一。很多人能背出代码但一旦要求现场讲思路就卡壳这说明他没有真正理解算法的每一步在干什么。冒泡排序的思路很简单每一轮从头到尾相邻两两比较如果前一个比后一个大就交换位置这样每一轮都会把当前范围内最大的元素“冒泡”到末尾。我推荐背这个优化版public static void bubbleSort(int[] arr) { int n arr.length; for (int i 0; i n - 1; i) { boolean swapped false; for (int j 0; j n - 1 - i; j) { if (arr[j] arr[j 1]) { int temp arr[j]; arr[j] arr[j 1]; arr[j 1] temp; swapped true; } } if (!swapped) { break; } } }关键有两个细节。第一内层循环的边界是n - 1 - i因为每一轮结束后数组末尾已经有i个元素排好序不需要再参与比较这个边界优化能减少一半的无谓比较。第二用swapped标志位判断本轮是否发生了交换如果某一轮从头到尾一个交换都没有说明数组已经有序直接退出循环。这种优化在面试里说出来是很加分的点。复杂度也要烂熟于心最坏和平均时间复杂度都是O(n²)最好情况已经有序可以优化到O(n)空间复杂度O(1)。冒泡排序是稳定排序因为相同元素不会交换顺序。这些概念面试官连环问的时候你要能顺着往下说。4.2 常用库函数algorithmArrays与CollectionsJava没有像C STL里那样叫“algorithm”的库但java.util.Arrays和java.util.Collections这两个工具类功能上完全对得上“常用库函数”这个词。Arrays主要用于操作数组最常用的是这几个方法作用示例Arrays.sort(arr)对数组升序排序排序int、String数组都非常方便Arrays.binarySearch(arr, key)二分查找数组必须先排序找不到返回负数Arrays.fill(arr, val)把数组所有元素填充为指定值初始化数组很常用Arrays.copyOf(arr, len)复制数组并指定新长度扩容新数组的标准手法Arrays.toString(arr)把数组转成可打印的字符串调试必备Collections则针对集合框架注意跟Collection区分。Collection是集合接口Collections是操作集合的工具类。经典的Collections.sort(list)可以对List排序还能传一个Comparator做自定义排序。比如你有一个Student对象列表想按成绩从高到低排写法是students.sort((s1, s2) - s2.getScore() - s1.getScore());泛型、Lambda、集合操作全揉在一起了这正好是Java基础的综合应用。我的建议是不要单独背这些API而是写一个小工具类把这些方法都用一遍打印结果看效果。纸上得来终觉浅这句话在编程学习里非常适用。4.3 蓝桥杯风格的实战题一道题串起所有知识点提到蓝桥杯初学者容易慌觉得算法竞赛离自己很远。其实蓝桥杯省赛的Java题目难度是循序渐进的很多题只要你基础扎实就能做出来。我在这里出一道典型的题读入一个正整数n然后读入n个整数按从小到大排序后输出如果过程中有相等的数只保留一个。这道题考察的内容非常综合输入输出Scanner、集合去重Set、排序Collections.sort、遍历输出。参考解法import java.util.*; public class Main { public static void main(String[] args) { Scanner sc new Scanner(System.in); int n sc.nextInt(); SetInteger set new TreeSet(); for (int i 0; i n; i) { set.add(sc.nextInt()); } ListInteger list new ArrayList(set); Collections.sort(list); for (int num : list) { System.out.print(num ); } } }这里用TreeSet就能在插入时自动排序也可以用HashSet加手动排序。重点在于去重用Set排序用Collections这两个工具用的熟不熟直接暴露基础扎不扎实。蓝桥杯的准备策略我个人建议是先把这类“语法组合题”刷熟而不是一上来啃动态规划和图论。基础题的代码越写越顺再上难度才有底气。5. 工程能力数据库、文件与后端拓展5.1 JDBC连接SQL Server 2008的老问题Java连接数据库最底层的方式是JDBC。这在实际项目中不一定直接用因为大家都会用MyBatis、Hibernate这类框架封装但JDBC的原理必须懂框架底层就是用这层能力跟数据库打交道的。热搜词里有一条“java如何连接sqlserver2008”这是一个典型的历史遗留问题SQL Server 2008是很老的版本它的默认协议和现在高版本的JDBC驱动兼容性不太好。连接老版本SQL Server有两个方案使用微软官方JDBC驱动sqljdbc4.jar或者在驱动URL里关闭加密。我实际可用的连接写法Class.forName(com.microsoft.sqlserver.jdbc.SQLServerDriver); String url jdbc:sqlserver://localhost:1433;DatabaseNameTestDB;encryptfalse;trustServerCertificatetrue; Connection conn DriverManager.getConnection(url, sa, your_password);注意encryptfalse和trustServerCertificatetrue这两个参数。老版本SQL Server默认不强制加密通信但新版JDBC驱动默认要求加密这俩参数不配上连接大概率报SSL错误。如果你用的是更老的jtds驱动连接串的格式又不一样是jdbc:jtds:sqlserver://localhost:1433/TestDB。很多时候网上教程给的写法不一样让你一头雾水其实区别就在驱动和参数上。另一个坑是驱动JAR包的放置。命令行运行JDBC程序时必须用-cp把驱动JAR和你的代码class一起带上或者把JAR丢到JDK_HOME\jre\lib\ext目录老版本JDK的做法否则运行时会报ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver。这个报错我见得太多了十次有八次不是代码问题就是驱动没加载进classpath。5.2 文件路径从Java到Android的路径差异热搜词里有一大串以/storage/emulated/0/android/data/...开头的路径还有content://开头的URI。这些都是Android里的文件访问路径跟你在纯Java里写的C:\Users\...完全不同源。我花点篇幅把这几类路径彻底说清楚。纯Java里读写文件用的是操作系统的文件系统路径比如File f new File(data/info.txt)这是相对当前工作目录。但Android是Linux内核路径风格是/开头根目录叫/。设备存储被挂载在/storage/emulated/0/这就是你通过文件管理器看到的“内部存储”根目录等价于旧版路径/sdcard/。那一长串/storage/emulated/0/Android/data/包名/files/...是应用专属目录app-specific directory。Android系统规定每个应用只能在自己专属目录里自由读写文件不需要额外申请存储权限这既是安全机制也是系统管理存储空间的方式。从Android 11API 30开始系统进一步收紧即使你有存储权限也不允许App直接读取其他应用专属目录下的文件这就是为什么你拿到一个/storage/emulated/0/Android/data/某应用/files/log/...路径后用文件管理器根本打不开。而content://开头的URI是ContentProvider提供的“内容URI”。它隐藏了真实文件路径只暴露一个抽象标识比如content://com.tencent.wework.fileprovider/external_path/android/data/...这通常是FileProvider生成的URI。App之间要分享文件官方推荐方式就是FileProvider加content URI因为直接传递file://路径在Android 7.0以上会抛FileUriExposedException。所以你在网上看到那些奇怪的路径本质是不同App用不同机制暴露存储位置属于正常的系统设计不是Bug。5.3 MyBatis-Plus实体类生成建表SQL的思路热搜词里还有一条偏后端的“mybatisplus根据java实体类生成创建表的sql语句”。虽然这一篇是Android前篇但我建议有志做全栈的同学稍微了解一点。MyBatis-Plus是MyBatis的增强工具它的核心功能是“实体类映射数据库表”。默认情况下一个Java实体类对应一张表驼峰命名的属性自动映射下划线命名的字段。比如TableName(user) public class User { TableId(type IdType.AUTO) private Long id; private String userName; private Integer age; }MyBatis-Plus会根据类名和字段名自动推断表名和列名所以“根据实体类生成建表SQL”这个需求本质上是对实体类做反射扫描拿到类的字段列表和类型再按数据库类型规则转换成CREATE TABLE语句。常见的字段类型映射规则如下Java类型MySQL类型Long / IntegerBIGINT / INTStringVARCHAR(255)LocalDateTimeDATETIMEBigDecimalDECIMAL(10, 2)BooleanTINYINT(1)很多低代码平台的建表功能核心就是这张映射表。我自己做过一个小工具通过反射拿到实体类字段后遍历拼接SQL字符串再对特殊字段追加索引和注释。整个过程不复杂但思路非常实用。如果你后端项目也想省掉手写SQL的麻烦可以按这个思路去做或者直接用MyBatis-Plus的AutoGenerator代码生成器它能生成实体类反推建表、生成Controller和Service一条龙搞定。6. 常见问题与排查技巧实录6.1 环境配置与编译运行的问题速查表下面这个表基本上涵盖了我带初学者以来大家问得最多的问题。每一条都是真实踩坑后总结出来的你可以直接CtrlF查问题现象根本原因解决办法提示java不是内部或外部命令PATH没配置或没生效重开终端检查%JAVA_HOME%\bin是否在PATH里java -version版本号和预期不一致安装了多个JDKPATH优先级不对用where java看实际使用的是哪个路径调整环境变量顺序Eclipse/IDE里代码不报错命令行javac报错项目使用的JDK和系统默认JDK不一致统一IDE和命令行的JDK版本Android Studio同步Gradle非常慢网络问题依赖下载失败配置镜像仓库或手动下载Gradle到本地dist目录程序启动报ClassNotFoundExceptionclasspath里缺少依赖JAR包检查构建路径或-cp参数是否包含所需JAR老服务器上JDK装完但系统不识别32位系统装了64位JDK重新下载32位JDK 8版本服务端端口被占用启动失败上一次进程没关干净用netstat查PID后结束进程或改启动端口排查环境问题有一个铁律先确认最基本的现象再层层往外找。比如App启动闪退先看有没有崩溃日志没有日志再查是不是代码问题比如JAR包导入报错先确认文件确实存在再确认驱动和代码版本匹配。很多折腾了一两个小时的问题最后只是路径冒号写错或者少了一个点。6.2 从Java过渡到Android的认知转变如果你已经下定决心学Android我建议提前在观念上做一个切换从“写逻辑跑结果”切换成“写界面、管生命周期、处理异步回调”。Java基础课程里你写的程序大多在main方法里一路跑完Android里没有main方法入口整个App是被系统的消息循环驱动着运行的。Android的四大组件Activity、Service、BroadcastReceiver、ContentProvider每一个都是Java类在整个App生命周期中的特殊形态。你的Java基础知识越扎实学习这些组件的速度会越快。很多新手卡住的地方不是组件本身而是回调解不开Activity的onCreate、onResume这些方法是谁在调用为什么我不调用它也会执行答案就在Java的回调机制——系统框架持有一堆组件对象在合适的时间点调用已经注册好的生命周期方法。这个概念你如果通过自定义接口回调亲手实现过一次就会豁然开朗。常见的扩展方向我也提一嘴如果对UI效果感兴趣后面会接触到进度条ProgressBar、协调布局加BannerCoordinatorLayout 轮播图这些都需要Java集合与动画基础如果对系统底层感兴趣可以学Android TV、Automotive OS这类特定平台开发但起步依然要先把Java基础补牢。另外Android测试也不是全新技术单元测试就是跑在JVM上的JUnit框架本身也是Java技术栈这块反而很适合作为Android初学者的第一个测试突破口。6.3 给自己的学习计划配一份实操清单学编程没有捷径但可以有“更省力的路径”。我建议在看完这篇“回炉”内容之后给自己安排一个一周的实操清单每项内容都不难但组合起来正好覆盖本篇所有知识点第一天重装或重配一次JDK环境用命令行javac和java完整编译运行一个带外部JAR包的工程。第二天用面向对象写一个“学生管理系统”包含Student类、ArrayList存储、Comparable排序最后用循环把菜单界面打出来。第三天抓一个常见的异常场景比如数组越界、空指针手动模拟抛出、捕获、finally执行的完整过程并打印日志。第四天手写冒泡排序和二分查找把Arrays和Collections里的常用方法各用一遍。第五天写一个JDBC连接本机数据库的程序插入几条数据并查询打印。第六天在Android Studio里建一个空项目用一个Button加一个TextView实现点击按钮把内容上传到另一个界面感受Activity和Intent的基础流程。第七天总结这一周遇到的问题整理一份自己的踩坑记录。这份清单看起来每条都很“基本功”但我带过的人里能坚持做完并写出总结的后续学Android的速度明显快于只刷视频不练手的。编程是一门动手的手艺活眼睛会了不代表手会了手会了才算是真会了。最后说一个我自己的实操体会Java这一关卡住很多人长时间的不是知识点本身而是“不知道这些东西有什么用”。等你真正体会到List是RecyclerView的数据源、接口回调是按钮点击的底层机制、多线程是网络请求的基石那种“原来如此”的感觉会让你对后续学习特别有信心。这篇回炉篇的定位就是把这种“联系感”建立起来后面不管是接着学Android基础还是转头做Java后端你都会踏实很多。