ホームページ > Java > &#&チュートリアル > Java 面接の質問集 - 内定をもらいやすくするために推奨される面接の質問

Java 面接の質問集 - 内定をもらいやすくするために推奨される面接の質問

php是最好的语言
リリース: 2019-12-28 16:06:22
オリジナル
2285 人が閲覧しました

はじめに

ハゲ頭だけが人を強くできる

以前ブログを書いていた時、よく書かれたブログが黙って集められていることに気づきました。最近抜け漏れのチェックをしていて、割と重要な知識点もあったのですが、以前のブログに書いていなかったので、空いた時間を利用して整理してみました(オススメ:JAVA面接問題集) )。

テキストの知識ポイント:

  • 整数定数プール

  • TCPのアンパックとスティッキング

  • select,pol,epoll単純な違いselect、poll、epoll简单区别

  • jdk1.6以后对Synchronize锁优化

  • Java内存模型

本文力求简单讲清每个知识点,希望大家看完能有所收获

一、神奇的Integer

前阵子在群上看有人在讨论关于Integer的true或者false问题,我本以为我已经懂了这方面的知识点了。但还是做错了,后来去请教了一下朋友。朋友又给我发了另一张图:

Java 面接の質問集 - 内定をもらいやすくするために推奨される面接の質問

后来发现这是出自《深入理解Java虚拟机——JVM高级特性与最佳实践(第2版)》中的10.3.2小节中~

public class Main_1 {
    public static void main(String[] args) {
        Integer a = 1;
        Integer b = 2;
        Integer c = 3;
        Integer d = 3;
        Integer e = 321;
        Integer f = 321;
        Long g = 3L;
        Long h = 2L;
        System.out.println(c == d);
        System.out.println(e == f);
        System.out.println(c == (a + b));
        System.out.println(c.equals(a + b));
        System.out.println(g == (a + b));
        System.out.println(g.equals(a + b));
        System.out.println(g.equals(a + h));
    }

}
ログイン後にコピー

你们可以先思考一下再往下翻看答案,看看能不能做对。

1.1解题思路

在解这道题之前,相信很多人都已经知道了,在Java中会有一个Integer缓存池,缓存的大小是:-128~127

Java 面接の質問集 - 内定をもらいやすくするために推奨される面接の質問答案是:

  • true

  • false

  • true

  • true

  • true

  • false

  • true

简单解释一下:

  • 使用==的情况:

    • 如果比较Integer变量,默认比较的是地址值

    • Java的Integer维护了从-128~127的缓存池

    • 如果比较的某一边有操作表达式(例如a+b),那么比较的是具体数值

  • 使用equals()的情况:

    • 无论是Integer还是Long中的equals()默认比较的是数值

    • Long的equals()方法,JDK的默认实现:会判断是否是Long类型

  • 注意自动拆箱,自动装箱问题。

Java 面接の質問集 - 内定をもらいやすくするために推奨される面接の質問

反编译一下看看:

import java.io.PrintStream;

public class Main_1 {
    public static void main(String[] paramArrayOfString) {
        Integer localInteger1 = Integer.valueOf(1);
        Integer localInteger2 = Integer.valueOf(2);
        Integer localInteger3 = Integer.valueOf(3);
        Integer localInteger4 = Integer.valueOf(3);
        Integer localInteger5 = Integer.valueOf(321);
        Integer localInteger6 = Integer.valueOf(321);
        Long localLong = Long.valueOf(3L);

        // 缓存池
        System.out.println(localInteger3 == localInteger4);
        
        // 超出缓存池范围
        System.out.println(localInteger5 == localInteger6);
        
        // 存在a+b数值表达式,比较的是数值
        System.out.println(localInteger3.intValue() == localInteger1.intValue() + localInteger2.intValue());

        // equals比较的是数值
        System.out.println(localInteger3.equals(Integer.valueOf(localInteger1.intValue() + localInteger2.intValue())));
        // 存在a+b数值表达式,比较的是数值
        System.out.println(localLong.longValue() == localInteger1.intValue() + localInteger2.intValue());
        // Long的equals()先判断传递进来的是不是Long类型,而a+b自动装箱的是Integer类型
        System.out.println(localLong.equals(Integer.valueOf(localInteger1.intValue() + localInteger2.intValue())));

        // ... 最后一句在这里漏掉了,大家应该可以推断出来
    }
}
ログイン後にコピー

我使用的反编译工具是jd-gui

  • jdk1.6以降の場合 同期ロックの最適化

Java メモリ モデル

この記事
    は各知識ポイントを簡単に説明するよう努めています
  • 、読んだ後に皆さんが何かを得ることができることを願っています

    1. グループ a の誰かを見ました。少し前 Integer の真偽の問題について議論するとき、私はこの知識点をすでに理解していると思っていました。しかし、それでも間違いを犯したので、友人にアドバイスを求めました。友達が別の写真を送ってくれました:
  • 1 .png

    後になって、これが「Java 仮想マシンの詳細な理解 - JVM の高度な機能とベスト プラクティス (第 2 版)」のセクション 10.3.2 からのものであることがわかりました~
  •     public void vectorTest(){
            Vector<String> vector = new Vector<String>();
            for(int i = 0 ; i < 10 ; i++){
                vector.add(i + "");
            }
    
            System.out.println(vector);
        }
    ログイン後にコピー
    ログイン後にコピー
  • それについて考えることができますまず答えを読んで正しく答えられるかどうかを確認してください。

    1.1 問題解決のアイデア
  • この問題を解決する前に、Java には整数キャッシュ プールがあり、キャッシュ サイズは -128~127 であることを多くの人がすでに知っていると思います。 img src="https://img.php.cn//upload/image/437/714/541/1533177807473997.png" title="1533177807473997.png" alt="Java 面接の質問集 - 内定をもらいやすくするために推奨される面接の質問"/>答えは:

  • tru​​e

  • false

  • tru​​e

  • tru​​e

  • tru​​e

  • false

tru​​e

Java 面接の質問集 - 内定をもらいやすくするために推奨される面接の質問簡単な説明:

を使用します== ケース:

    整数変数を比較する場合、デフォルトの比較は

    アドレス値です

    Java の Integer は -128~127 のキャッシュ プールを維持します

    比較の片側に演算式がある場合 (a+b など)、比較は次のようになります。 特定の値

    🎜🎜🎜🎜equals() の使用: 🎜🎜
      🎜🎜いいえInteger か Long か? equals() のデフォルトは 🎜数値🎜 です。 🎜🎜🎜🎜JDK のデフォルト実装である Long の equals() メソッド: 🎜それが Long 型であるかどうかを判断します🎜🎜🎜🎜🎜🎜自動アンボックス化と自動ボックス化の問題に注意してください。 🎜🎜🎜🎜Java 面接の質問集 - 内定をもらいやすくするために推奨される面接の質問 🎜🎜逆コンパイルして見てください: 🎜rrreee🎜 私が使用する逆コンパイル ツールは jd-gui です。まだ逆コンパイルを試したことがない場合は、ダウンロードして試してみてください: 🎜🎜🎜 🎜https://github.com/java-decompiler/jd-gui/releases 🎜🎜🎜🎜 2. 同期ロックの最適化メソッドとは何ですか🎜🎜 マルチスレッドの記事レビュー: 🎜🎜🎜🎜ThreadLocal はとてもシンプルです 🎜🎜🎜 🎜3分でマルチスレッド ドアに入ることができます! 🎜🎜🎜🎜スレッドソースコード解析🎜🎜🎜🎜マルチスレッドの基礎知識ポイント!マルチスレッドを学習し、半分の労力で 2 倍の結果を得る方法について読んでください🎜🎜🎜🎜Java ロック メカニズムについて学び🎜🎜🎜🎜AQS を簡単に見てみましょう🎜🎜🎜🎜それについて学ぶにはサブクラスをロックしてください🎜🎜🎜🎜スレッド プール、それについて本当に知りたくないですか? 🎜🎜🎜🎜マルチスレッドのデッドロックはとても単純です🎜🎜🎜🎜Javaマルチスレッドを支援する3人の若者🎜🎜🎜🎜以前マルチスレッドの記事を書いたときに、同期ロックは次の後に発生すると簡単に言いましたjdk1.6 スピン ロックへの適応、ロックの削除、ロックの粗密化、軽量ロック、バイアスされたロックなど、さまざまな最適化があります。 🎜🎜🎜🎜🎜これらの最適化は非常に理解するのが難しいと思っていましたが、実は~~​​~簡単に理解するだけで簡単に理解できます。 🎜🎜2.1 スピンロックに適応する🎜🎜ロック競合はカーネルモードで行われ、ユーザーモードからカーネルモードへの🎜切り替え🎜が行われますが、これには非常に時間がかかります。 🎜🎜🎜スピンロック🎜が表示される理由は、ほとんどの場合、🎜ロックの占有はカーネルモードに切り替えるのにかかる時間よりも短い時間しか続かない🎜ため、その前にスレッドを待機させてください。カーネル モードに入る 限られた時間内にロックを取得できれば、多くの無駄な時間が回避されます。そうでない場合は、カーネル モードに移行してロックを獲得します。 🎜🎜JDK 1.6 で適応型スピン ロックが導入されました。これは、🎜スピンの時間が固定されず、スピンするかどうかに関係なく、よりスマートになる🎜ことを意味します。 🎜

      自旋锁在JDK1.4.2中就已经引入,只不过默认是关闭的,可以使用-XX:+UseSpinning参数来开启,在JDK1.6中就已经改为默认开启了。

      2.2锁消除

      如果JVM明显检测到某段代码是线程安全的(言外之意:无锁也是安全的),JVM会安全地原有的锁消除掉!

      比如说:

          public void vectorTest(){
              Vector<String> vector = new Vector<String>();
              for(int i = 0 ; i < 10 ; i++){
                  vector.add(i + "");
              }
      
              System.out.println(vector);
          }
      ログイン後にコピー
      ログイン後にコピー

      Vector是默认加锁的,但JVM如果发现vector变量仅仅在vectorTest()方法中使用,那该vector是线程安全的。JVM会把vector内部加的锁去除,这个优化就叫做:锁消除。

      2.3锁粗化

      默认情况下,总是推荐将同步块的作用范围限制得尽量小

      但是如果一系列的连续操作都对同一个对象反复加锁和解锁,甚至加锁操作是出现在循环体中的,频繁地进行互斥同步操作也会导致不必要的性能损耗

      JVM会将加锁的范围扩展(粗化),这就叫做锁粗化。

      2.4轻量级锁

      轻量级锁能提升程序同步性能的依据是“对于绝大部分的锁,在整个同步周期内都是不存在竞争的”,这是一个经验数据。

      • 如果没有竞争,轻量级锁使用CAS操作避免了使用互斥量的开销

      • 但如果存在锁竞争,除了互斥量的开销外,还额外发生了CAS操作,因此在有竞争的情况下,轻量级锁会比传统的重量级锁更慢。

      简单来说:如果发现同步周期内都是不存在竞争,JVM会使用CAS操作来替代操作系统互斥量。这个优化就被叫做轻量级锁。

      2.5偏向锁

      偏向锁就是在无竞争的情况下把整个同步都消除掉,连CAS操作都不做了

      偏向锁可以提高带有同步但无竞争的程序性能。它同样是一个带有效益权衡(Trade Off)性质的优化,也就是说,它并不一定总是对程序运行有利,如果程序中大多数的锁总是被多个不同的线程访问,那偏向模式就是多余的。在具体问题具体分析的前提下,有时候使用参数-XX:-UseBiasedLocking来禁止偏向锁优化反而可以提升性能。

      2.6简单总结各种锁优化

      • 自适应偏向锁:自旋时间不固定

      • 锁消除:如果发现代码是线程安全的,将锁去掉

      • 锁粗化:加锁范围过小(重复加锁),将加锁的范围扩展

      • 轻量级锁:在无竞争的情况下使用CAS操作去消除同步使用的互斥量

      • 偏向锁:在无竞争环境下,把整个同步都消除,CAS也不做。

      参考资料:

      • https://blog.csdn.net/chenssy/article/details/54883355

      三、TCP粘包,拆包

      这是在看wangjingxin大佬面经的时候看到的面试题,之前对TCP粘包,拆包没什么概念,于是就简单去了解一下。

      3.1什么是拆包粘包?为什么会出现?

      在进行Java NIO学习时,可能会发现:如果客户端连续不断的向服务端发送数据包时,服务端接收的数据会出现两个数据包粘在一起的情况。

      TCP的首部格式:

      Java 面接の質問集 - 内定をもらいやすくするために推奨される面接の質問

      • TCP是基于字节流的,虽然应用层和TCP传输层之间的数据交互是大小不等的数据块,但是TCP把这些数据块仅仅看成一连串无结构的字节流,没有边界

      • 从TCP的帧结构也可以看出,在TCP的首部没有表示数据长度的字段

      基于上面两点,在使用TCP传输数据时,才有粘包或者拆包现象发生的可能。

      一个数据包中包含了发送端发送的两个数据包的信息,这种现象即为粘包

      Java 面接の質問集 - 内定をもらいやすくするために推奨される面接の質問

      接收端收到了两个数据包,但是这两个数据包要么是不完整的,要么就是多出来一块,这种情况即发生了拆包和粘包

      Java 面接の質問集 - 内定をもらいやすくするために推奨される面接の質問

      拆包和粘包的问题导致接收端在处理的时候会非常困难(因为无法区分一个完整的数据包)

      3.2 アンパックとスティッキングの問題を解決する

      サブパッケージ化メカニズムには一般に 2 つの 共通 ソリューションがあります:

      • 1、特殊文字制御

      • 2、ヘッダーの大文字にデータ パケットの長さを追加する

      netty を使用する場合は、解凍と貼り付けの問題を解決するための特別なエンコーダーとデコーダーがあります。

      ヒント:UDP にはパケット固着問題はありませんが、パケット損失やパケット障害が発生します。不完全なパッケージは存在せず、受け取ったパッケージはすべて完全に正しいものになります。送信されるデータ ユニット プロトコルは UDP メッセージまたはユーザー データグラムであり、送信時に結合も分割もされません。

      4. select、poll、epoll の簡単な違い

      NIO レビュー:

      • JDK10 がリリースされました。nio についてどれくらい知っていますか?

      これは Linux で I/O 再利用モデルを実装する方法です:

      select/poll/epoll 関数の 1 つを呼び出し、複数のファイル記述子がある場合は Return if を渡します。ファイル記述子の準備ができている場合は、タイムアウトになるまでブロックされます。 select/poll/epoll其中一个函数,传入多个文件描述符,如果有一个文件描述符就绪,则返回,否则阻塞直到超时。

      这几个函数是有些区别的,可能有的面试官会问到这三个函数究竟有什么区别:

      区别如下图:

      Java 面接の質問集 - 内定をもらいやすくするために推奨される面接の質問

      两句话总结:

      • select和poll都需要轮询每个文件描述符,epoll基于事件驱动,不用轮询

      • select和poll每次都需要拷贝文件描述符,epoll不用

      • select最大连接数受限,epoll和poll最大连接数不受限

      tips:epoll在内核中的实现,用红黑树管理事件块

      4.1通俗例子

      现在3y在公司里边实习,写完的代码需要给测试测一遍。

      select/poll情况:

      • 开发在写代码,此时测试挨个问所有开发者,你写好程序了没有?要测试吗?

      epoll

      これらの関数にはいくつかの違いがあります。一部の面接官は、これら 3 つの関数の違いは何かと尋ねるかもしれません:
      • 違いは次のとおりです:

        Java 面接の質問集 - 内定をもらいやすくするために推奨される面接の質問
      2 文での要約:

      選択してポーリング epoll はイベント駆動型であり、ポーリングは必要ありません

      select and poll は毎回ファイル記述子をコピーする必要があります。 epoll は使用されません

      select 接続の最大数は制限されています。epoll と Paul 接続の最大数は制限されていません
      • ヒント: カーネルでの epoll の実装では、イベント ブロックの管理に赤黒ツリーが使用されます
      4.1 よくある例

      現在、3 歳は会社でインターン中であり、書かれたコードをテストする必要があります。

      select/poll 状況:

      Java 面接の質問集 - 内定をもらいやすくするために推奨される面接の質問開発者はコードを書いています。この時点で、テストはすべての開発者に 1 つずつ尋ねます

      、プログラムの作成は完了しましたか?テストしたいですか?

      Java 面接の質問集 - 内定をもらいやすくするために推奨される面接の質問epoll 状況:

        開発者はコードを書き終え、テスターに​​「コードを書きました。テストしてください。関数は XXX です。」と伝えます。そこでテスターは喜んでバグを探しました。
      • その他の一般的な説明 [1]:

      • バーテンダー (スレッド)、酔っぱらいのグループが彼の前に横たわり、突然そのうちの 1 人が「飲み物を注いで」と叫び (事件)、あなたは駆け寄って注ぐ彼に飲み物を飲ませて、それから彼を放してください、そして突然別の人がワインを注ぎたいと思ったので、あなたはそれを注ぎに行きます。 時々、ウェイターは多くの人にワインを提供しませんが、ウェイターは暇であり、注ぐことができます。他のことをしたり、携帯電話で遊んだりします。 epollとselectに関して言えば、pollとpollの違いは、後者の2つのシーンでは酔った人々が話さないことと、飲み物が欲しいかどうかを1人ずつ尋ねる必要があり、携帯電話をいじる時間がないことです。 。 io の多重化はおそらく、これらの酔っ払いがウェイターを共有することを意味します。
      • その他の一般的な説明 [2]: 簡単な例を挙げると (あまり鮮明ではないかもしれませんが)、レストランのウェイター (カーネル) を選択/ポーリングすると、ホテルのオーナー (ユーザー プログラム) に次のように伝えます。このウェイターを知っている人は、ゲストがどのテーブルの料金を払っているのかをボスに伝えてください。上司は各テーブルに行って「支払いますか?」と尋ねなければなりません。 epoll ホテルのウェイター (カーネル) はホテルのオーナー (ユーザー プログラム) に次のように指示します。「ゲスト 1、2、5 はチェックアウトします。ボスはテーブル 1、2、5 に直接行ってお金を受け取ることができます5」。 Java メモリ モデル

      • JVM ブログ投稿レビュー:
      • JVM はどのようにして始めてから諦めるまでに至ったのですか?

      • 以前 JVM を書いていたとき、
      JVM メモリ構造と Java メモリ モデルを混同したことがあります

      ~~~ 幸いなことに、何人かの熱心なネチズンがそれを私に指摘してくれました。 JVM メモリ構造:

      • Java メモリ モデル:
      • 🎜 変数を操作するときの規則: 🎜🎜🎜🎜Java メモリ モデルでは、すべての 🎜 変数がメイン メモリに格納されることが規定されています 🎜🎜🎜🎜🎜スレッド 🎜ワーキングメモリ🎜は、スレッドによって使用される変数のメインメモリ🎜コピーコピー🎜🎜🎜🎜🎜を保存します。スレッドによる変数のすべての🎜操作🎜は、🎜ワーキングメモリ🎜で実行される必要があります。メインメモリ内の変数を直接読み書きすることはできません🎜🎜🎜🎜 🎜作業メモリからメインメモリへの同期🎜は、次の8つの操作を通じて実装されます: 🎜🎜🎜🎜lock (ロック): メインメモリ内の変数に作用します。メモリ 、変数をスレッド専用としてマークします。 🎜🎜🎜🎜unlock (アンロック): メインメモリ変数に作用して、ロック状態にある変数を解放します。解放された変数のみが他のスレッドによってロックされます。 🎜
      • read (読み取り): メインメモリ変数に作用し、変数値をメインメモリからスレッドの作業メモリに転送し、後続のロードアクションで使用できるようにします

      • load (ロード) : 作業メモリ変数に作用し、読み取り操作によってメイン メモリから取得した変数値を作業メモリ内の変数のコピーに置きます。

      • use (使用): 作業メモリ内の変数に作用し、作業メモリ内の変数値を実行エンジンに渡します。これは、仮想マシンがその値を使用する必要があるバイトコード命令に遭遇するたびに実行されます。変数を操作します。

      • assign (割り当て): 作業メモリ内の変数に作用し、実行エンジンから受け取った値を作業メモリ内の変数に割り当てます。これは、仮想マシンが値を割り当てるバイトコード命令に遭遇するたびに実行されます。変数に操作します。

      • store (ストレージ): 作業メモリ内の変数に作用し、後続の書き込み操作のために作業メモリ内の変数の値をメインメモリに転送します。

      • write (書き込み): メインメモリ内の変数に作用し、作業メモリ内の変数の値からメインメモリ内の変数にストア操作を転送します。

      Java メモリ モデルは、同時プロセスでの原子性、可視性、順序付けの処理方法を中心に構築されています

      これら 3 つの特性

      原子性を保証する操作:
      • read、load、assign、use、store和write

      • 同期ロック

      順序性を保証する操作 (並べ替えると無秩序になります):
      • volatile
      • 同期ロック

      可視性の保証:
      • volatile
      • 同期ロック
      • ファイナル

      として上で述べたように、順序性は揮発性ロックと同期ロックによって保証できますが、プログラムを作成するときにコードの順序性を常に意識するわけではありません。実際、Java には、happens-before 原則(happens-before)

      • と呼ばれる原則があります。「happens-before」原則は、いくつかの

        を介して同時環境で 2 つの問題を解決するために使用できます。ルール すべての問題 オペレーション間で競合が発生する可能性があるかどうか

      • これらのルールがあり、私たちの
      • オペレーションはこれらのルールで定義された範囲内にあります

        。操作 A が操作 B より前に確実に実行されることを確認できます (並べ替えの問題は発生しません)

      • 「前に発生する」原則には次のようなものがあります:

        プログラム シーケンス ルール (プログラム順序ルール):スレッドでは、プログラム コードの順序に従って、前に書かれた操作は後ろに書かれた操作より前に発生します。分岐やループなどの構造を考慮する必要があるため、正確には、プログラム コードのシーケンスではなく、制御フローのシーケンスになります。
      • モニターロックルール: ロック解除操作は、同じロックに対する後続のロック操作の前に発生します。ここで強調しなければならないのは、同じロックであり、「後で」とは時間的な順序を指します。
      • 揮発性変数のルール: 揮発性変数への書き込み操作が最初に発生し、その後に変数への読み取り操作が発生します。ここでの「後で」とは、時間的な順序も指します。スレッド開始ルール: Thread オブジェクトの start() メソッドは、このスレッドのすべてのアクションに先行します。
      • スレッド終了ルール: スレッド内のすべての操作は、Thread.join() メソッド、Thread.isAlive() の戻り値などによって終了するときに最初に発生します。は実行を終了しました。
      • スレッド割り込みルール: スレッド割り込み() メソッドの呼び出しは、割り込みが発生したスレッドのコードが割り込みイベントの発生を検出する前に最初に発生します。割り込みが発生したかどうかは、 Thread.interrupted() メソッドを通じて検出できます。
      • オブジェクトファイナライザールール: オブジェクトの初期化 (コンストラクター実行の終了) は、finalize() メソッドの開始時に最初に行われます。
      • 推移性: 操作 A が操作 B の前に発生し、操作 B が操作 C の前に発生した場合、操作 A は操作 C の前に発生すると結論付けることができます。
      • 関連記事:


      Java での面接の質問の概要を共有する

      古典的な Java メインメソッドの面接の質問 10 選

      以上がJava 面接の質問集 - 内定をもらいやすくするために推奨される面接の質問の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート