作为一名优秀的Android开发者,我们一定要有自己完备的知识体系。
Java作为移动应用开发中不可以或缺的部分,是我们每个Android开发者都必须具备的技能,掌握的越多,对我们的成长进阶就越有利。今天我们就来系统盘点一下,Android开发者成长中必须掌握的Java核心知识点。废话不多说,我们直接开始。(友情提示:内容太过硬核且十分“干”,请自备饮品。)
Java基础
一、Java的面向对象思想
二、Java中的多态
三、Java中的异常处理机制
四、Java中的容器Java高阶
一、深入泛型
二、注解深入浅出
三、并发编程
四、数据传输与序列化
五、Java虚拟机原理
六、反射与类加载
七、高效IO
继承:继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类(超类、基类);得到继承信息的类被称为子类(派生类)。继承让变化中的软件系统有了一定的延续性,同时继承也是封装程序中可变因素的重要手段。
封装:通常认为封装是把数据和操作数据的方法绑定起来,对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装;我们编写一个类就是对数据和数据操作的封装。可以说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口。
多态:多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单的说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。如果将对象的方法视为对象向外界提供的服务,那么运行时的多态性可以解释为:当A 系统访问B 系统提供的服务时,B 系统有多种提供服务的方式,但一切对A 系统来说都是透明的。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。运行时的多态是面向对象最精髓的东西,要实现多态需要做两件事:1. 方法重写(子类继承父类并重写父类中已有的或抽象的方法);2. 对象造型(用父类型引用引用子类型对象,这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为)。
抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。
答:靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,而程序调用的方法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法。
1)按照异常需要处理的时机分为编译时异常也叫CheckedException 和运行时异常也叫RuntimeException。只有java 语言提供了Checked 异常,Java 认为Checked 异常都是可以被处理的异常,所以Java 程序必须显式处理Checked 异常。如果程序没有处理Checked 异常,该程序在编译时就会发生错误无法编译。这体现了Java 的设计哲学:没有完善错误处理的代码根本没有机会被执行。对Checked 异常处理方法有两种:1 当前方法知道如何处理该异常,则用try...catch 块来处理该异常。2 当前方法不知道如何处理,则在定义该方法是声明抛出该异常。
运行时异常只有当代码在运行时才发行的异常,编译时不需要try catch。Runtime 如除数是0 和数组下标越界等,其产生频繁,处理麻烦,若显示申明或者捕获将会对程序的可读性和运行效率影响很大。所以由系统自动检测并将它们交给缺省的异常处理程序。当然如果你有处理要求也可以显示捕获它们。
Java 对异常进行了分类,不同类型的异常分别用不同的Java 类表示,所有异常的根类为java.lang.Throwable,Throwable 下面又派生了两个子类:Error 和Exception,Error 表示应用程序本身无法克服和恢复的一种严重问题。Exception 表示程序还能够克服和恢复的问题,其中又分为系统异常和普通异常,系统异常是软件本身缺陷所导致的问题,也就是软件开发人员考虑不周所导致的问题,软件使用者无法克服和恢复这种问题,但在这种问题下还可以让软件系统继续运行或者让软件死掉,例如,数组脚本越界(ArrayIndexOutOfBoundsException),空指针异常(NullPointerException)、类转换异常(ClassCastException);普通异常是运行环境的变化或异常所导致的问题,是用户能够克服的问题,例如,网络断线,硬盘空间不够,发生这样的异常后,程序不应该死掉。
java 为系统异常和普通异常提供了不同的解决方案,编译器强制普通异常必须try..catch 处理或用throws 声明继续抛给上层调用方法处理,所以普通异常也称为checked 异常,而系统异常可以处理也可以不处理,所以,编译器不强制用try..catch 处理或用throws 声明,所以系统异常也称为unchecked 异常。
其实HashMap主干是一个数组叫Note:
transient Node[] table;
而Node是HashMap里面的一个静态类:
static class Node implements Map.Entry { final int hash;//对key的hashcode值进行hash运算后得到的值,存储在Note,避免重复计算 final K key; V value; Node next;//存储指向下一个Entry的引用,单链表结构 Node(int hash, K key, V value, Node next) { this.hash = hash; this.key = key; this.value = value; this.next = next; } ... }
看到上面代码Node里面的next,是一个单链表结构,而结合table是一个Node数组,可以判断出HashMap是一个数组加链表的结构。下面我总结一下HashMap的结构图:
已知一个HashMap集合, User 有name(String)和age(int)属性。请写一个方法实现对HashMap 的排序功能,该方法接收HashMap为形参,返回类型为HashMap,要求对HashMap 中的User 的age 倒序进行排序。排序时key=value 键值对不得拆散。
Tips:要做出这道题必须对集合的体系结构非常的熟悉。HashMap 本身就是不可排序的,但是该道题偏偏让给HashMap 排序,那我们就得想在API 中有没有这样的Map 结构是有序的,LinkedHashMap,对的,就是他,他是Map 结构,也是链表结构,有序的,更可喜的是他是HashMap 的子类,我们返回LinkedHashMap即可,还符合面向接口(父类编程的思想)。但凡是对集合的操作,我们应该保持一个原则就是能用JDK 中的API 就有JDK 中的API,比如排序算法我们不应该去用冒泡或者选择, 而是首先想到用Collections 集合工具类。
public class HashMapTest {public static void main(String[] args) {HashMap users = new HashMap<>();users.put(1, new User("张三", 25));users.put(3, new User("李四", 22));users.put(2, new User("王五", 28));System.out.println(users);HashMap sortHashMap = sortHashMap(users);System.out.println(sortHashMap);/*** 控制台输出内容* {1=User [name=张三, age=25], 2=User [name=王五, age=28], 3=User [name=李四,age=22]}{2=User [name=王五, age=28], 1=User [name=张三, age=25], 3=User [name=李四,age=22]}*/}public static HashMap sortHashMap(HashMap map) {// 首先拿到map 的键值对集合Set> entrySet = map.entrySet();// 将set 集合转为List 集合,为什么,为了使用工具类的排序方法List> list = new ArrayList>(entrySet);// 使用Collections 集合工具类对list 进行排序,排序规则使用匿名内部类来实现Collections.sort(list, new Comparator>() {@Overridepublic int compare(Entry o1, Entry o2) {//按照要求根据User 的age 的倒序进行排return o2.getValue().getAge()-o1.getValue().getAge();}});//创建一个新的有序的HashMap 子类的集合LinkedHashMap linkedHashMap = new LinkedHashMap();//将List 中的数据存储在LinkedHashMap 中for(Entry entry : list){linkedHashMap.put(entry.getKey(), entry.getValue());}//返回结果return linkedHashMap;}}
1.HashMap 是线程不安全的,HashMap 是一个接口,是Map 的一个子接口,是将键映射到值得对象,不允许键值重复,允许空键和空值;由于非线程安全,HashMap 的效率要较HashTable 的效率高一些.
2.HashTable 是线程安全的一个集合,不允许null 值作为一个key 值或者Value 值;
3.HashTable 是sychronize,多个线程访问时不需要自己为它的方法实现同步,而HashMap 在被多个线程访问的时候需要自己为它的方法实现同步;
1)CPU核心数、线程数2)CPU时间片轮转机制
1)synchronized内置锁2)volatile 关键字3)线程私有变量 ThreadLocal
1)什么是CAS?2)CAS(Compare And Swap)导致的ABA问题
1)Java中的ThreadPoolExecutor类2)深入剖析线程池实现原理3)如何合理配置线程池的大小
1.概念
2.用途 对象的序列化主要有两种用途:1)把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中。2)在网络上传送对象的字节序列。
一种数据传输格式,与开发语言无关,轻量级。一开始是javaScript的,但是后面比较流传,几乎所有语言都有相应的使用API。
1)如何判断对象已“死”2)回收方法区3)垃圾回收算法
1)对象优先在Eden分配2)大对象直接进入老年代3)长期存活的对象将进入老年代4)动态对象年龄判定5)空间分配担保
1)Dalvik指令2)Dalvik启动过程3)Dalvik上的垃圾回收
1)反射基本概念与三种获取Class对象的方式2)获取构造器实例化对象与属性信息3)Android 配置打包签名信息的两种方法4)Hook动态注入代码
1)动态代理模式2)Android 中的Dalvik和ART3)ClassLoader 的构造函数4)双亲委派机制
1)文件流:FileInputStream/FileOutputStream, FileReader/FileWriter
2)包装流:PrintStream/PrintWriter/Scanner
3)字符串流:StringReader/StringWriter
4)转换流:InputStreamReader/OutputStreamReader
5)缓冲流:BufferedReader/BufferedWriter , BufferedInputStream/BufferedOutputStream
其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
虽然 Android 没有前几年火热了,已经过去了会四大组件就能找到高薪职位的时代了。这只能说明 Android 中级以下的岗位饱和了,现在高级工程师还是比较缺少的,很多高级职位给的薪资真的特别高(钱多也不一定能找到合适的),所以努力让自己成为高级工程师才是最重要的。
对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。
所以,最后这里放上我耗时两个月,将自己9年Android开发的知识笔记整理成的Android开发者必知必会系统学习资料笔记,上述知识点在笔记中都有详细的解读,里面还包含了腾讯、字节跳动、阿里、百度2019-2020面试真题解析,并且把每个技术点整理成了视频和PDF(知识脉络 + 诸多细节)。
还有 高级架构技术进阶脑图、高级进阶架构资料 帮助大家学习提升进阶,这里我也免费分享给大家,网上的资料五花八门,零散杂乱而不成体系,学习效率非常低。相信我的笔记可以给大家节省大部分时间用来多陪陪家人孩子。关注后私信我【学习】就可以无偿获取了。
最后,赠与大家一句诗,共勉!学习最好的时机,就是现在!!
不驰于空想,不骛于虚声。不忘初心,方得始终!