

▐オブジェクト指向の3大特徴
-
Java と C++ の違い
-
ポリモーフィック実装の原則
ポリモーフィズムの基礎となる実装は動的バインディングであり、実行時にメソッド呼び出しとメソッド実装を関連付けます。
静的バインディングと動的バインディング:
1 つはコンパイル時に決定され、メソッドのオーバーロードなどの静的ディスパッチと呼ばれます。
1 つは実行時に決定され、メソッドのオーバーライド (書き換え) やインターフェイスの実装など、動的ディスパッチと呼ばれます。
ポリモーフィックな実装
現在のメソッド呼び出しのスタック フレーム (ローカル変数テーブル、操作スタック、動的接続、リターン アドレス) は仮想マシン スタックに保存されます。ポリモーフィズムの実装プロセスは、メソッド呼び出しの動的ディスパッチのプロセスです。サブクラスが親クラスのメソッドをオーバーライドする場合、ポリモーフィック呼び出しでは、動的バインディング プロセスが最初に実際の型がサブクラスであると判断します。まずサブクラスメソッドを検索します。このプロセスがメソッド カバレッジの本質です。
静的キーワードと最終キーワード
-
抽象クラスとインターフェイス
-
抽象クラスもインターフェイスもインスタンス化できません。 -
抽象クラスとインターフェイスの両方で抽象メソッドを定義でき、サブクラス/実装クラスはこれらの抽象メソッドをオーバーライドする必要があります。
-
抽象クラスにはコンストラクターがありますが、インターフェイスにはコンストラクターがありません。 -
抽象クラスには通常のメソッドを含めることができ、インターフェイスはパブリック抽象 (Java 8 以降で使用可能) を使用して抽象メソッドのみを変更できます。 -
抽象クラスは 1 回のみ継承できますが、インターフェイスは複数回継承できます。 -
抽象クラスはさまざまなタイプのメンバー変数を定義でき、インターフェイスは public static Final によって変更される静的定数のみにすることができます。
-
ジェネリックとジェネリック消去
-
リフレクションの原理と使用シナリオ
1.类名.class(就是一份字节码)
2.Class.forName(String className);根据一个类的全限定名来构建Class对象
3.每一个对象多有getClass()方法:obj.getClass();返回对象的真实类型
使用するシーン:
共通のフレームワークを開発する- リフレクションの最も重要な用途は、さまざまな共通のフレームワークを開発することです。多くのフレームワーク (Spring など) が構成されています (XML ファイルを介して JavaBeans やフィルターなどを構成するなど) フレームワークの汎用性を確保するには、さまざまなオブジェクトまたはクラスを動的にロードし、それに応じてさまざまなメソッドを呼び出す必要があります。実行時の構成ファイル。
-
動的プロキシ - アスペクト プログラミング (AOP) では、特定のメソッドをインターセプトする必要があります。通常、動的プロキシ メソッドが選択されます。このとき、それを実現するにはリフレクション技術が必要となります。 JDK: Spring のデフォルトの動的プロキシはインターフェースを実装する必要があります。
CGLIB: asm フレームワークを介してバイト ストリームをシリアル化します。構成可能ですが、パフォーマンスは低下します。 カスタム アノテーション- アノテーション自体はマークとしてのみ機能します。アノテーション マークに従ってアノテーション インタプリタを呼び出し、動作を実行するには、リフレクション メカニズムを使用する必要があります。
Java例外システム
Throwable は、Java 言語のすべてのエラーまたは例外のスーパー クラスです。次のレベルはエラーと例外に分かれています。
エラー:
Java ランタイム システムの内部エラーおよびリソース枯渇エラーを指します。アプリケーションはこのクラスのオブジェクトをスローしません。このようなエラーが発生した場合、ユーザーに通知するだけでなく、残りはプログラムを安全に終了することを試みます。
例外に含まれるもの:RuntimeException、CheckedException;
プログラミング エラーは、構文エラー、論理エラー、操作エラーの 3 つのカテゴリに分類できます。
構文エラー(コンパイル エラーとも呼ばれます) は、コンパイル プロセス中に発生するエラーで、コンパイラによって構文エラーがチェックされます。
論理エラーとは、プログラムの実行結果が期待と一致しないことを意味し、デバッグによってエラーの原因を突き止めて発見することができます。
実行時エラーはプログラムの異常終了を引き起こすエラーであり、実行時エラーは例外処理によって処理する必要があります。
RuntimeException:実行時例外。プログラムは論理的な観点からそのような例外を回避するように努める必要があります。
NullPointerException、ClassCastException など。
CheckedException:チェックされた例外。プログラムは trycatch を使用してキャッチし、処理します。
IOException、SQLException、NotFoundExceptionなど;
▐ 数据结构
ArrayList和LinkedList
ArrayList:
底层基于数组实现,支持对元素进行快速随机访问,适合随机查找和遍历,不适合插入和删除。(提一句实际上)
默认初始大小为10,当数组容量不够时,会触发扩容机制(扩大到当前的1.5倍),需要将原来数组的数据复制到新的数组中;当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。
LinkedList:
底层基于双向链表实现,适合数据的动态插入和删除;
内部提供了List接口中没有定义的方法,用于操作表头和表尾元素,可以当作堆栈、队列和双向队列使用。(比如jdk官方推荐使用基于linkedList的Deque进行堆栈操作)
ArrayList与LinkedList区别:
都是线程不安全的,ArrayList适用于查找的场景,LinkedList适用于增加、删除多的场景。
实现线程安全:
可以使用原生的Vector,或者是Collections.synchronizedList(List list)函数返回一个线程安全的ArrayList集合。
建议使用concurrent并发包下的CopyOnWriteArrayList的。
①Vector:底层通过synchronize修饰保证线程安全,效率较差。
②CopyOnWriteArrayList:写时加锁,使用了一种叫写时复制的方法;读操作是可以不用加锁的。
List遍历快速和安全失败
普通for循环遍历List删除指定元素
for(int i=0; i < list.size(); i++){
if(list.get(i) == 5)
list.remove(i);
}
迭代遍历,用list.remove(i)方法删除元素
Iterator<Integer> it = list.iterator();
while(it.hasNext()){
Integer value = it.next();
if(value == 5){
list.remove(value);
}
}
foreach遍历List删除元素
for(Integer i:list){
if(i==3) list.remove(i);
}
fail—fast:快速失败
当异常产生时,直接抛出异常,程序终止。
fail-fast主要是体现在当我们在遍历集合元素的时候,经常会使用迭代器,但在迭代器遍历元素的过程中,如果集合的结构(modCount)被改变的话,就会抛出异常ConcurrentModificationException,防止继续遍历。这就是所谓的快速失败机制。
fail—safe:安全失败
采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历。由于在遍历过程中对原集合所作的修改并不能被迭代器检测到,所以不会触发ConcurrentModificationException。
缺点:基于拷贝内容的优点是避免了ConcurrentModificationException,但同样地,迭代器并不能访问到修改后的内容,即:迭代器遍历的是开始遍历那一刻拿到的集合拷贝,在遍历期间原集合发生的修改迭代器是不知道的。
场景:java.util.concurrent包下的容器都是安全失败,可以在多线程下并发使用,并发修改。
详细介绍HashMap
角度:数据结构+扩容情况+put查找的详细过程+哈希函数+容量为什么始终都是2^N,JDK1.7与1.8的区别。
参考:https://www.jianshu.com/p/9fe4cb316c05
数据结构:
HashMap在底层数据结构上采用了数组+链表+红黑树,通过散列映射来存储键值对数据。
扩容情况:
默认的负载因子是0.75,如果数组中已经存储的元素个数大于数组长度的75%,将会引发扩容操作。
【1】创建一个长度为原来数组长度两倍的新数组。
【2】1.7采用Entry的重新hash运算,1.8采用高于运算。
put操作步骤:

-
ConcurrentHashMap

序列化和反序列化
序列化的意思就是将对象的状态转化成字节流,以后可以通过这些值再生成相同状态的对象。对象序列化是对象持久化的一种实现方法,它是将对象的属性和方法转化为一种序列化的形式用于存储和传输。反序列化就是根据这些保存的信息重建对象的过程。
-
实现了数据的持久化,通过序列化可以把数据永久地保存到硬盘上(通常存放在文件里)Redis的RDB -
利用序列化实现远程通信,即在网络上传送对象的字节序列。Google的protoBuf。
String
StringBuffer对方法加了同步锁,线程安全,效率略低于StringBuilder。
▐ 设计模式与原则
单例模式
-
工厂模式
抽象工厂模式
提供一个接口,用于创建相关或者依赖对象的家族,并由此进行约束。
面试题
▐ 构造方法
构造方法可以被重载,只有当类中没有显性声明任何构造方法时,才会有默认构造方法。
构造方法没有返回值,构造方法的作用是创建新对象。
▐ 初始化块
静态初始化块的优先级最高,会最先执行,在非静态初始化块之前执行。
静态初始化块会在类第一次被加载时最先执行,因此在main方法之前。
▐ This
关键字this代表当前对象的引用。当前对象指的是调用类中的属性或方法的对象。
关键字this不可以在静态方法中使用。静态方法不依赖于类的具体对象的引用。
▐ 重写和重载的区别
重载指在同一个类中定义多个方法,这些方法名称相同,签名不同。
重写指在子类中的方法的名称和签名都和父类相同,使用override注解。
▐ Object类方法
toString默认是个指针,一般需要重写;
equals比较对象是否相同,默认和==功能一致;
hashCode散列码,equals则hashCode相同,所以重写equals必须重写hashCode;
finalize用于垃圾回收之前做的遗嘱,默认空,子类需重写;
clone深拷贝,类需实现cloneable的接口;
getClass反射获取对象元数据,包括类名、方法;
notify、wait用于线程通知和唤醒;
▐ 基本数据类型和包装类

本文分享自微信公众号 - 大淘宝技术(AlibabaMTT)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。