Javaインタビュー質問の全集(9)

Javaインタビュー質問の全集(9)

BaiyuITハハ

80.トランザクションのACIDとは何ですか?

回答:

  • アトミック:トランザクション内のすべての操作が実行されるか、まったく実行されません。いずれかの操作が失敗すると、トランザクション全体が失敗します。
  • 一貫性:トランザクションが終了した後、システム状態は一貫性があります。
  • 分離(分離):同時に実行されるトランザクションは、互いの中間状態を確認できません。
  • 耐久性:壊滅的な障害が発生した場合でも、トランザクションの完了後に行われた変更は保持されます。ログと同期バックアップにより、障害が発生した後にデータを再構築できます。

補足:事務に関しては、面接で聞かれる可能性が非常に高く、質問できることがたくさんあります。最初に知っておくべきことは、トランザクションは同時データアクセスがある場合にのみ必要であるということです。複数のトランザクションが同じデータにアクセスする場合、3種類のデータ読み取りの問題(ダーティ読み取り、繰り返し不可能な読み取り、ファントム読み取り)と2種類のデータ更新の問題(タイプ1の欠落した更新とタイプ2)を含む5種類の問題が発生する可能性があります。更新を失った)。

ダーティ読み取り:トランザクションAはトランザクションBのコミットされていないデータを読み取り、これに基づいて動作し、トランザクションBはロールバックを実行し、Aによって読み取られたデータはダーティデータです。

Javaインタビュー質問の全集(9)

繰り返し不可の読み取り:トランザクションAは、以前に読み取ったデータを再読み取りし、データが別のコミットされたトランザクションBによって変更されていることを検出します。

Javaインタビュー質問の全集(9)

ファントム読み取り:トランザクションAはクエリを再実行し、クエリ条件を満たす一連の行を返します。トランザクションBによって送信された行が挿入されていることがわかります。
時間統計量トランザクションA転送トランザクションB
Javaインタビュー質問の全集(9)
タイプ1失われた更新:トランザクションAがキャンセルされると、送信されたトランザクションBの更新されたデータが上書きされます。
Javaインタビュー質問の全集(9)
2番目のタイプの失われた更新:トランザクションAは、トランザクションBがコミットしたデータを上書きし、トランザクションBの操作が失われる原因になります。
Javaインタビュー質問の全集(9)

データへの同時アクセスによって引き起こされる問題は、一部のシナリオでは許可される場合がありますが、一部のシナリオでは致命的となる場合があります。データベースは通常、テーブルレベルのロックとさまざまなロックオブジェクトに応じたロックに分割できるロックメカニズムを介してデータへの同時アクセスの問題を解決します。行レベルのロックは、同時トランザクションのロック関係に応じて、共有ロックと排他ロックに分けることができます。情報を確認して、特定の内容を理解することができます。
ロックを直接使用するのは非常に面倒です。このため、データベースはユーザーに自動ロックメカニズムを提供します。ユーザーがセッションのトランザクション分離レベルを指定する限り、データベースはSQLステートメントを分析し、トランザクションによってアクセスされるリソースに適切なロックを追加します。さらに、データベースはまた、これらのロックを維持して、ユーザーに対して透過的なさまざまな手段を通じてシステムのパフォーマンスを向上させます(つまり、理解する必要はありません。実際、私にはわかりません)。次の表に示すように、ANSI / ISO SQL 92標準では、4つのレベルのトランザクション分離レベルが定義されています。
Javaインタビュー質問の全集(9)

トランザクション分離レベルとデータアクセスの同時実行性は反対であることに注意してください。トランザクション分離レベルが高いほど、同時実行性は低下します。したがって、特定のアプリケーションに応じて適切なトランザクション分離レベルを決定する必要があります。この場所には普遍的な原則はありません。

81. JDBCでトランザクションを処理するにはどうすればよいですか?

回答:接続はトランザクション処理の方法を提供します。setAutoCommit(false)を呼び出すことで、トランザクションを手動でコミットするように設定できます。トランザクションが完了したら、commit()を使用してトランザクションを明示的にコミットします。トランザクション処理中に例外が発生した場合は、rollback()を使用してトランザクションを実行します。ロールバックします。さらに、セーブポイントの概念がJDBC 3.0から導入され、コードを介してセーブポイントを設定し、トランザクションを指定されたセーブポイントにロールバックできるようになりました。
Javaインタビュー質問の全集(9)

82. JDBCはBlobとClobを処理できますか?

回答:BlobはBinary Large Objectを指し、ClobはCharacter Large Objecを指すため、Blobは大きなバイナリデータを格納するように設計されており、Clobは大きなテキストデータを格納するように設計されています。そして設計されました。JDBCのPreparedStatementとResultSetはどちらも、BlobおよびClob操作をサポートするための対応するメソッドを提供します。次のコードは、JDBCを使用してLOBを操作する方法を示しています。
例としてMySQLデータベースを取り上げ、ID、名前、写真を含む3つのフィールドを持つユーザーテーブルを作成します。テーブルステートメントは次のとおりです。


create table tb_user
(id int primary key auto_increment,
name varchar(20) unique not null,
photo longblob );

次のJavaコードは、データベースにレコードを挿入します。


import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
class JdbcLobTest {
    public static void main(String[] args) {
        Connection con = null;
        try {
            // 1. 加载驱动(Java6以上版本可以省略)
            Class.forName("com.mysql.jdbc.Driver");
            // 2. 建立连接
            con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123456");
            // 3. 创建语句对象
            PreparedStatement ps = con.prepareStatement("insert into tb_user values (default, ?, ?)");
            ps.setString(1, "骆昊");              // 将SQL语句中第一个占位符换成字符串
            try (InputStream in = new FileInputStream("test.jpg")) {    // Java 7的TWR
                ps.setBinaryStream(2, in);      // 将SQL语句中第二个占位符换成二进制流
                // 4. 发出SQL语句获得受影响行数                System.out.println(ps.executeUpdate() == 1 ? "插入成功" : "插入失败");
            } catch(IOException e) {
                System.out.println("读取照片失败!");
            }
        } catch (ClassNotFoundException | SQLException e) {     // Java 7的多异常捕获
            e.printStackTrace();
        } finally { // 释放外部资源的代码都应当放在finally中保证其能够得到执行
            try {
                if(con != null && !con.isClosed()) {                    con.close();    // 5. 释放数据库连接 
                    con = null;     // 指示垃圾回收器可以回收该对象
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

83.通常の表現とその使用法について簡単に説明します。

回答:文字列を処理するプログラムを作成する場合、特定の複雑なルールを満たす文字列を見つける必要があることがよくあります。正規表現は、これらのルールを説明するために使用されるツールです。言い換えれば、正規表現はテキストルールを記録するコードです。

注:コンピューターの誕生当初、処理される情報のほとんどは数値でしたが、時間が経ちました。現在、コンピューターを使用して数値よりも情報を処理することが多くなっていますが、文字列です。文字列の照合と処理には、正規の式が最も強力です。ツール、ほとんどの言語は正規表現のサポートを提供します。

84. Javaは通常の式操作をどのようにサポートしますか?

回答:JavaのStringクラスは、matches()、replaceAll()、replaceFirst()、split()などの通常の式操作をサポートするメソッドを提供します。さらに、Patternクラスは、Javaで正規式オブジェクトを表すために使用できます。これは、さまざまな正規式操作のための豊富なAPIを提供します。以下のインタビュー質問のコードを参照してください。

インタビューの質問:-文字列から最初の英語の左括弧の前に文字列を傍受したい場合、例:北京(チャオヤン地区)(西城地区)(ハイディアン地区)、傍受結果は次のとおりです:北京、その後通常の式書き方?


import java.util.regex.Matcher;import java.util.regex.Pattern;
class RegExpTest {
    public static void main(String[] args) {
        String str = "北京市(朝阳区)(西城区)(海淀区)";
        Pattern p = Pattern.compile(".*?(?=\\()");
        Matcher m = p.matcher(str);
        if(m.find()) {
            System.out.println(m.group());
        }
    }
}
  • 14

注:上記の通常式では、レイジーマッチングと先読みが使用されています。これらの内容がよくわからない場合は、インターネットでよく知られている「通常式30分チュートリアル」を読むことをお勧めします。

85.クラスオブジェクトを取得する方法は何ですか?

回答:

  • 方法1:Type.class、例:String.class
  • メソッド2:Object.getClass()、例: "hello" .getClass()
  • 方法3:Class.forName()、例如:Class.forName( "java.lang.String")

    86.反射によってオブジェクトを作成するにはどうすればよいですか?

    回答:

  • メソッド1:クラスオブジェクトを介してnewInstance()メソッドを呼び出します。例:String.class.newInstance()
  • 方法2:クラスオブジェクトのgetConstructor()またはgetDeclaredConstructor()メソッドを介してConstructorオブジェクトを取得し、そのnewInstance()メソッドを呼び出してオブジェクトを作成します。例:String.class.getConstructor(String.class).newInstance( "Hello" );

    87.リフレクションを介してオブジェクトのプライベートフィールドの値を取得および設定するにはどうすればよいですか?

    回答:クラスオブジェクトのgetDeclaredField()メソッドを使用してFieldオブジェクトを設定し、フィールドオブジェクトのsetAccessible(true)を介してアクセスできるように設定してから、get / setメソッドを介してフィールドの値を取得/設定できます。アップ。次のコードは、リフレクティブツールクラスを実装します。2つの静的メソッドを使用して、プライベートフィールドの値を取得および設定します。フィールドは、基本タイプまたはオブジェクトタイプにすることができ、ReflectionUtil.get(などのマルチレベルオブジェクト操作をサポートします。 dog、 "owner.car.engine.id"); dogオブジェクトの所有者の車のエンジンのID番号を取得できます。


import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
/** * 反射工具类 * @author 骆昊 * */
public class ReflectionUtil {
    private ReflectionUtil() {
        throw new AssertionError();
    }
    /**     * 通过反射取对象指定字段(属性)的值     * @param target 目标对象     * @param fieldName 字段的名字     * @throws 如果取不到对象指定字段的值则抛出异常     * @return 字段的值     */
    public static Object getValue(Object target, String fieldName) {
        Class<?> clazz = target.getClass();
        String[] fs = fieldName.split("\\.");
        try {
            for(int i = 0; i < fs.length - 1; i++) {
                Field f = clazz.getDeclaredField(fs[i]);
                f.setAccessible(true);
                target = f.get(target);
                clazz = target.getClass();
            }
            Field f = clazz.getDeclaredField(fs[fs.length - 1]);
            f.setAccessible(true);
            return f.get(target);
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**     * 通过反射给对象的指定字段赋值     * @param target 目标对象     * @param fieldName 字段的名称     * @param value 值     */
    public static void setValue(Object target, String fieldName, Object value) {
        Class<?> clazz = target.getClass();
        String[] fs = fieldName.split("\\.");
        try {
            for(int i = 0; i < fs.length - 1; i++) {
                Field f = clazz.getDeclaredField(fs[i]);
                f.setAccessible(true);
                Object val = f.get(target);
                if(val == null) {
                    Constructor<?> c = f.getType().getDeclaredConstructor();
                    c.setAccessible(true);
                    val = c.newInstance();
                    f.set(target, val);
                }
                target = val;
                clazz = target.getClass();
            }
            Field f = clazz.getDeclaredField(fs[fs.length - 1]);
            f.setAccessible(true);
            f.set(target, value);
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

88.リフレクションを介してオブジェクトのメソッドを呼び出す方法は?

回答:以下のコードを参照してください。


import java.lang.reflect.Method;
class MethodInvokeTest {
    public static void main(String[] args) throws Exception {
        String str = "hello";
        Method m = str.getClass().getMethod("toUpperCase");
        System.out.println(m.invoke(str));  // HELLO
    }
}

89.オブジェクト指向の「6つの原則と1つのルール」について簡単に説明します。

回答:

  • 単一責任の原則:クラスは、すべきことだけを行います。(単一の責任の原則は「高い結束」を表現したいと考えており、コードを書く最終的な原則は、ひまわりの本や悪霊の剣の中心的な考えが「欲望」であるように、わずか6語の「高い結束、低い結合」です。この演習を実践するには、まず宮殿から来なければなりません。」いわゆる高凝集性とは、コードモジュールが1つの機能のみを完了することを意味します。オブジェクト指向では、1つのクラスだけが実行できるようになっている場合、それとは関係のない領域は含まれません。高い結束の原則を実践するこのクラスの責任は1つだけです。「焦点が合っているので、とてもプロフェッショナル」という言葉は誰もが知っています。オブジェクトがあまりにも多くの責任を負うと、何もしない運命にあります。この世界上記の良い点には2つの特徴があります。1つは単一の機能を備えていることです。優れたカメラはテレビショッピングで販売されている種類のマシンではありません。100を超える機能を備えています。基本的に写真を撮ることしかできません。もう1つはモジュール式です。良い自転車とは組み立てられた自転車です。ショックアブソーバーからブレーキ、トランスミッションまで、すべての部品を分解して組み立てることができます。良いピンポンラケットは完成したラケットではありません。自分で分解して組み立てることができるのはベースプレートとゴムでなければなりません。 、優れたソフトウェアシステム。ソフトウェアの再利用という目標を達成するために、その中の各機能モジュールを他のシステムでも簡単に使用できる必要があります。)
  • 開閉の原則:ソフトウェアエンティティは、拡張のために開いており、変更のために閉じている必要があります。(理想的な状態では、ソフトウェアシステムに新しい関数を追加する必要がある場合、元のコード行を変更せずに、元のシステムからいくつかの新しいクラスを派生させるだけで済みます。開く方法と閉じる方法は2つあります。キーポイント:①抽象化が鍵です。システムに抽象クラスやインターフェースシステムがない場合、拡張ポイントはありません。②可変性をカプセル化し、複数の可変要素が混在している場合は、システム内のさまざまな可変要素を継承構造にカプセル化します。同時に、システムは複雑で混沌とします。変動性をカプセル化する方法がわからない場合は、「デザインパターンの詳細」という本のブリッジパターンに関する章を参照してください。)
  • 反転の原理に依存します:インターフェース指向のプログラミング。(原則は単純で具体的です。メソッドパラメータタイプ、メソッドリターンタイプ、および変数参照タイプを宣言するときは、抽象タイプはそのサブタイプのいずれでも使用できるため、具体的なタイプではなく、可能な限り抽象タイプを使用してください。置換については、以下のリヒター置換原則を参照してください。)
    リヒター置換原則:親タイプはいつでもサブタイプに置き換えることができます。(リヒター置換原理の説明に関しては、バーバラ・リスコフ氏の説明はこれよりもはるかに複雑ですが、簡単に言えば、スーパータイプを使用できる場所であればどこでもサブタイプを使用できます。リヒター置換原理は、継承関係が妥当かどうかを確認できます。継承関係がリヒター置換の原則に違反している場合は、継承関係が間違っている必要があり、コードをリファクタリングする必要があります。たとえば、猫を犬から継承させる、犬を猫から継承させる、正方形を長方形から継承させることは、すべて間違った継承関係です。 、リヒター置換の原則に違反するシーンを簡単に見つけることができるため。子クラスは親クラスよりも多くの機能を備えているため、子クラスは親クラスの能力を下げるのではなく、親クラスの能力を上げる必要があることに注意してください。もちろん、オブジェクトを能力の低いオブジェクトとして使用しても問題はありません。)
  • インターフェイスの分離の原則:インターフェイスは小さくて特殊である必要があり、大きくて包括的であってはなりません。(肥大化したインターフェースはインターフェースを汚染します。インターフェースは能力を表現するため、インターフェースは1種類の能力のみを記述し、インターフェースも非常にまとまりがある必要があります。たとえば、Qinqi、書道、絵画は、ではなく4つのインターフェースとして設計する必要があります。 1つのインターフェースで4つのメソッドに設計されている場合、このインターフェースは使いにくいため、1つのインターフェースで4つのメソッドに設計する必要があります。結局のところ、ピアノ、チェス、書道、絵画の4つすべてに精通している人はまだ少数であり、4つのインターフェースに設計されている場合は、いくつかの項目でいくつかのインターフェイスが実装されます。このように、各インターフェイスが再利用される可能性が非常に高くなります。Javaのインターフェイスは、機能、規則、および役割を表します。インターフェイスを正しく使用できるかどうかは、プログラミングレベルのレベルである必要があります。重要なマーク。)
  • 合成集約再利用の原則:集約または合成関係再利用コードの使用を優先します。(すべての教科書は例外なく継承を促進し、初心者を誤解させるため、継承によるコードの再利用は、オブジェクト指向のプログラミングで最も悪用されるものです。クラスには3つのタイプがあります。リレーションシップ、Is-Aリレーションシップ、Has-Aリレーションシップ、Use-Aリレーションシップは、それぞれ継承、関連付け、依存関係を表します。これらの中で、関連付けリレーションシップは、関連付けの強さに応じて、関連付け、集約、統合にさらに分類できますが、すべてです。 Has-A関係、複合集約再利用の原則は、コードを再利用するためにIs-A関係ではなくHas-A関係が優先されることを表現したいと考えています。理由はBaiduで10,000の理由で見つけることができます。 Java APIでの継承の悪用の例も多数あります。たとえば、PropertiesクラスはHashtableクラスを継承し、StackクラスはVectorクラスを継承します。これらの継承は明らかに間違っています。より良いアプローチは、PropertiesクラスにHashtableタイプのメンバーを配置することです。キーと値を文字列に設定してデータを保存します。また、Stackクラスの設計では、VectorオブジェクトをStackクラスに配置してデータを保存する必要があります。覚えておいてください:ツールクラスはいつでも継承しないでください。継承せずに使用できます。)
  • ディミットの法則:ディミットの法則は、最小知識の原則とも呼ばれます。オブジェクトは、他のオブジェクトについてできるだけ知識が少ない必要があります。(デメテルの法則は、単に「低結合」を実現する方法を意味します。ファサードモデルとメディエーターモデルは、デメテルの法則の実践です。ファサードモデルの場合、簡単な例を挙げて、会社に行ってビジネスを交渉します。会社が社内でどのように機能しているかを理解する必要はありません。会社について何も知る必要はありません。行くときは、会社の入り口にあるフロントデスクで美しさを見つけて、何をするかを伝えるだけです。彼らはフォローする適切な人を見つけます。連絡すると、フロントデスクの美しさは会社のシステムのファサードです。システムがどれほど複雑であっても、ユーザーにシンプルなファサードを提供できます。JavaWeb開発のフロントエンドコントローラーとしてのサーブレットまたはフィルターは単なるファサードではありませんか?ブラウザーからサーバーへ動作モードは不明ですが、フロントコントローラーからご要望に応じて対応サービスをご利用いただけます。メディエーターモードは、コンピューター、CPU、メモリー、ハードディスク、グラフィックカード、サウンドカードなどの簡単な例で説明することもできます。さまざまなデバイスが連携して動作する必要がありますが、これらを直接接続すると、コンピュータの配線が非常に複雑になります。この場合、マザーボードがメディエーターのように見え、各デバイスを次の図に示すように、各デバイス間でデータを直接交換する必要がないため、システムの結合と複雑さが軽減されます。ディミットのルールは、見知らぬ人に対処しないために一般的な単語を使用することです。必要です、あなたの友達を見つけて、彼にあなたのために見知らぬ人に対処させてください。)

Javaインタビュー質問の全集(9)
Javaインタビュー質問の全集(9)

90.知っているデザインパターンを簡単に説明してください。

回答:いわゆるデザインパターンは、繰り返し使用されてきた一連のコードデザインエクスペリエンスの要約です(状況の問題に対する実証済みのソリューション)。デザインパターンの使用は、コードを再利用可能にし、他の人が理解しやすくし、コードの信頼性を確保することです。デザインパターンにより、成功したデザインやアーキテクチャをより簡単かつ便利に再利用できます。実績のあるテクノロジーをデザインパターンに表現することで、新しいシステム開発者がデザインのアイデアを理解しやすくなります。
GoFの「DesignPatterns:Elements of Reusable Object-Oriented Software」では、3つのタイプ(作成されたタイプ[クラスのインスタンス化プロセスの要約]と構造タイプ[クラスまたはオブジェクトを組み合わせてより多くを形成する方法を説明します]大規模な構造]、行動[異なるオブジェクト間の責任とアルゴリズムの分割を抽象化])、以下を含む合計23の設計パターン:抽象ファクトリー(抽象ファクトリー)、ビルダー(ビルダー)、ファクトリーメソッド(ファクトリーメソッド(ファクトリーメソッドモード)、プロトタイプ(元のモデルモード)、シングルトン(シングルトンモード)、ファサード(ファサードモード)、アダプター(アダプターモード)、ブリッジ(ブリッジモード)、コンポジット(コンポジットモード)、デコレーター(装飾モード)、フライウェイト(フライウェイトモード)、プロキシ(エージェントモード);コマンド(コマンドモード)、インタープリター(インタープリターモード)、ビジター(ビジターモード)、イテレーター(反復サブモード)、メディエーター(メディエーターモード)、メモ(メモモード) )、オブザーバー(オブザーバーモード)、状態(状態モード)、戦略(戦略モード)、テンプレートメソッド(テンプレートメソッドモード)、責任の連鎖(責任の連鎖モード)。
インタビューでデザインパターンの知識について尋ねられたとき、次のような最も頻繁に使用される回答を選ぶことができます。

  • ファクトリパターン:ファクトリクラスは、条件に応じて異なるサブクラスインスタンスを生成できます。これらのサブクラスは、共通の抽象親クラスを持ち、同じメソッドを実装しますが、これらのメソッドは、異なるデータに対して異なる操作(ポリモーフィックメソッド)を実行します。サブクラスのインスタンスを取得した後、開発者は、サブクラスのどのインスタンスが返されるかを考慮することなく、基本クラスのメソッドを呼び出すことができます。
  • プロキシモード:オブジェクトにプロキシオブジェクトを提供すると、プロキシオブジェクトが元のオブジェクトの参照を制御します。実際の開発では、エージェントは、使用目的に応じて、リモートエージェント、仮想エージェント、保護エージェント、キャッシュエージェント、ファイアウォールエージェント、同期エージェント、およびインテリジェント参照エージェントに分類できます。
  • アダプターパターン:あるクラスのインターフェースをクライアントが期待する別のインターフェースに変換し、インターフェースの不一致のために一緒に使用できないクラスが一緒に機能できるようにします。
  • テンプレートメソッドパターン:抽象クラスを提供し、具体的なメソッドまたはコンストラクターの形式でロジックの一部を実装してから、いくつかの抽象メソッドを宣言して、サブクラスに残りのロジックを実装させます。さまざまなサブクラスが、さまざまなビジネスロジックを実現するために、さまざまな方法でこれらの抽象メソッド(ポリモーフィック実装)を実装できます。
    また、上記のファサードモード、ブリッジモード、シングルトンモード、デコレーションモード(コレクションツールやI / Oシステムではデコレーションモードを使用)についてもお話しできます。とにかく、基本は最も身近なものを選ぶことです。答えは、見逃さないように、最も頻繁に使用されます

おすすめ

転載: blog.51cto.com/15061944/2593697
おすすめ