Java Road to God:Javaインタビューの準備(10)

6、IO流

6.1シリアル化とは何ですか?シリアル化を実現する方法

シリアル化は、オブジェクトストリームを処理するためのメカニズムです。いわゆるオブジェクトストリームは、オブジェクトのコンテンツをストリーミングすることです。ストリーミングされたオブジェクトはネットワーク間で送信できます。シリアル化は、オブジェクトストリームの読み取りおよび書き込み操作によって引き起こされる問題を解決するためのものです。

シリアル化の実装:シリアル化する必要があるクラスのSerializableインターフェースを実装します

7.ネットワークプログラミング

8.例外処理

8.1Javaで例外をカスタマイズする方法

Exceptionクラスを継承します

//或者继承RuntimeException(运行时异常) 
public class MyException extends Exception {
    
     
 
  private static final long serialVersionUID = 1L; 
 
  // 提供无参数的构造方法
  public MyException() {
    
     
  } 
 
  // 提供一个有参数的构造方法,可自动生成
  public MyException(String message) {
    
     
    super(message);// 把参数传递给Throwable的带String参数的构造方法 
  } 
 
} 

8.2 Javaの2種類の例外は何ですか?それらの違いは何ですか

Javaには、チェックされた例外とチェックされていない例外の2種類の例外があり、コンパイル済み例外およびランタイム例外とも呼ばれます。

チェックされた例外(コンパイル例外):この例外は、throwsステートメントを使用してメソッドまたはクラスで宣言するか、try ... catchを使用してキャッチする必要があります。一般的に、IDEAのようなスマートコンパイラはそれを直接検出できます

未チェックの例外(実行時例外):プログラムの実行後に発生する例外(配列の添え字が範囲外、OOMなど)。

8.3Javaの例外とエラーの違いは何ですか

ExceptionとErrorはどちらもThrowableのサブクラスです。

例外は、プログラムの通常の操作で予想される予期しない状況であり、それに応じて対処できます。

エラーが発生すると、プログラムは異常で回復不能な状態になります

8.4スローとスローの違いは何ですか

スロー:

1.メソッドに作用します。これは、特定の例外がスローされることを意味します。これは、メソッド本体のステートメントによって処理されます。

2.具体的にスローされるアクション。つまり、スローされるのは異常なエンティティクラスです。throwを実行すると、何らかの例外をスローする必要があります

スロー:

1.メソッドの宣言に基づいて動作します。つまり、例外がスローされた場合、メソッドの呼び出し元が例外を処理します。

2.主な目的は、このメソッドが特定のタイプの例外をスローすることを宣言して、ユーザーが例外のタイプを認識できるようにすることです。

3.異常は可能性があり、必ずしも発生するとは限りません

9.クラスとオブジェクト

9.1クラスとオブジェクトの関係

クラスはオブジェクトの抽象化であり、オブジェクトはクラスの具体的なインスタンスです。クラスは抽象的でメモリを占有しませんが、オブジェクトは具象的でストレージスペースを占有します。クラスは、オブジェクトを作成するための青写真であり、特定のタイプのオブジェクトに含まれるメソッドと変数を定義するソフトウェアテンプレートです。

クラスとオブジェクトは、図面とオブジェクトの関係、および型と鋳造の関係のようなものです。

9.2プロセス指向とオブジェクト指向の違い

どちらもソフトウェア開発のアイデアであり、最初はプロセス指向、次にオブジェクト指向です。大規模プロジェクトでは、プロセス指向の欠点に対処するために、オブジェクト指向の開発アイデアが導入されます。

比喩

プロセス指向は卵チャーハン、オブジェクト指向はご飯をトッピングしたものです。お椀の利点は、「お皿」と「ご飯」が分離されていることで、お椀作りの柔軟性が向上します。食事に満足できない場合は食事を変更し、満足できない場合は食事を変更してください。ソフトウェア工学の用語は、「保守性」が優れており、「ファン」と「カイ」の結合度が比較的低いということです。

違い

さまざまなプログラミングのアイデア:プロセス指向は関数を実現する関数の開発に焦点を当てていますが、オブジェクト指向は最初にクラス、属性、メソッドを抽象化し、次にクラスをインスタンス化してメソッドを実行することで関数を完成させます。

カプセル化:すべてにカプセル化がありますが、プロセス指向のカプセル化は機能であり、オブジェクト指向のカプセル化はデータと機能です。

オブジェクト指向には継承とポリモーフィズムがありますが、プロセス指向には継承とポリモーフィズムがないため、オブジェクト指向の利点は明らかです。

9.3オブジェクト指向の特徴は何ですか?人生の例を使って説明してください

オブジェクト指向の3つの特性:カプセル化、継承、およびポリモーフィズム。

抽象化:抽象化は、データの抽象化や動作の抽象化など、オブジェクトのクラスの共通の特性を要約することによってクラスを構築するプロセスです。抽象化は、オブジェクトのプロパティと動作にのみ注意を払い、これらの動作の詳細には注意を払いません。

カプセル化:カプセル化は、データとデータの操作方法をバインドすることであると一般に考えられており、データへのアクセスは、定義されたインターフェイスを介してのみ行うことができます。オブジェクト指向の本質は、現実の世界を一連の完全に自律的で閉じたオブジェクトとして表現することです。クラスに書き込むメソッドは、実装の詳細の一種のカプセル化です。クラスを作成するのは、データとデータ操作のカプセル化です。カプセル化とは、隠すことができるすべてのものを隠すことであり、外の世界に最も単純なプログラミングインターフェイスを提供するだけであると言えます。

生活の中でテレビを見ると、液晶テレビは非常に薄いですが、内部の構造は非常に複雑です。ユーザーとして、私たちはそれを使用する方法を知る必要があるだけです。

継承:継承は、既存のクラスから継承情報を取得して新しいクラスを作成するプロセスです。継承情報を提供するクラスは親クラス(スーパークラス、基本クラス)と呼ばれ、継承情報を取得するクラスはサブクラス(派生クラス)と呼ばれます。継承により、変化するソフトウェアシステムに一定の継続性を持たせることができます。継承は、プログラム内の可変要素をカプセル化する重要な手段でもあります。

ポリモーフィズム:ポリモーフィズムとは、異なるサブタイプのオブジェクトが同じメッセージに対して異なる応答をすることを許可することを指します。簡単に言えば、同じオブジェクト参照で同じメソッドを呼び出しますが、実行方法は異なります。ポリモーフィズムは、コンパイル時のポリモーフィズムとランタイムポリモーフィズムに分けられます。オブジェクトのメソッドがオブジェクトによって外界に提供されるサービスと見なされる場合、実行時の多態性は次のように説明できます。システムAがシステムBによって提供されるサービスにアクセスする場合、システムBにはサービスを提供する複数の方法があります。しかし、すべてが正しいシステムは透過的です(電気シェーバーがAシステムであるように、その電源システムはBシステムであり、Bシステムはバッテリー電源またはAC電源、さらには太陽エネルギーを使用できます。AシステムはBタイプのみを通過しますオブジェクト電力供給の方法を呼び出しますが、電力供給システムの基礎となる実装が何であり、それがどのように電力を獲得したかを知りません)。メソッドのオーバーロード(オーバーロード)はコンパイル時のポリモーフィズム(プリバインディングとも呼ばれます)を実現し、メソッドのオーバーライド(オーバーライド)はランタイムのポリモーフィズム(ポストバインディングとも呼ばれます)を実現します。実行時のポリモーフィズムはオブジェクト指向の本質です。ポリモーフィズムを実現するには、次の2つのことを行う必要があります。1。メソッドの書き換え(サブクラスは親クラスを継承し、親クラスの既存または抽象メソッドを書き換えます)。オブジェクトモデリング(親タイプを使用してサブタイプオブジェクトを参照するため、同じメソッドを呼び出す同じ参照は、サブタイプオブジェクトに応じて異なる動作を示します)。

9.4静的内部クラスと内部クラスの違いは何ですか

静的内部クラスは、外部クラスへの参照を持つ必要はありません。ただし、非静的内部クラスは、外部クラスへの参照を保持する必要があります。

静的内部クラスは静的メンバー(メソッド、プロパティ)を持つことができますが、非静的内部クラスは静的メンバー(メソッド、プロパティ)を持つことはできません。

非静的内部クラスは、外部クラスの静的メンバーと非静的メンバーにアクセスできます。静的内部クラスは外部クラスの非静的メンバーにアクセスできませんが、外部クラスの静的メンバーにのみアクセスできます。

インスタンス化の方法は異なります。

  1. 静的内部クラス:外部クラスのインスタンスに依存せず、内部クラスオブジェクトを直接インスタンス化します

  2. 非静的内部クラス:外部クラスのオブジェクトインスタンスを介して内部クラスオブジェクトを生成します

9.5クラスの読み込みとポリモーフィック呼び出しの順序

public class ClassLoadTest {
    
    
    public static void main(String[] args) {
    
    
        A a=new B();
        System.out.println(a.x);

    }
}

class A{
    
    
     int x=5;

    static {
    
    
        System.out.println("static A");
    }

    {
    
    
        System.out.println("AAAAAAAAAAAAAAA");
    }

    public A(){
    
    
        System.out.println("A的构造函数");
    }

}

class B extends A{
    
    
     int x=10;

    static {
    
    
        System.out.println("static B");
    }

    {
    
    
        System.out.println("BBBBBBBBBBBB");
    }

    public B(){
    
    
        System.out.println("B的构造函数");
    }

}

9.6バイトコードを知っていますか?バイトコードは何ですか?整数x = 5、int y = 5、x == yを比較するために実行された手順

1.バイトコードの実行はスタック上で実行されます。

2. JDKのコンパイラを介して、javac(javaコンパイラ)コマンドを使用して、JVMで使用するためにソースコードをバイトコードファイル(.class)にコンパイルします。次に、classLoaderクラスローダーを介してバイトコードをロードします。javaソースコード- ->。classバイトコードにコンパイル-> CLロードバイトコード->バイトコードベリファイア->バイトコードインタープリター->ハードウェア

3.バイトコード命令とは:monitorenter命令、monitorexit命令:バイトコードの対応する位置でロックおよびロック解除;
iadd / ladd / fadd / dadd命令:int / long / float / doubleの追加、上の2つの数字をポップスタック、合計がスタックの一番上にプッシュされた後;サブ:減算
ロード命令:ローカル変数をスタックにロードします;ストア命令:スタック内のデータをローカル変数テーブルに保存します
新しい命令:オブジェクトを作成します; dup命令:最上位のオペランド値のスタックをコピーします

4. Spring AOP、ORMフレームワーク、およびホットデプロイメントでのバイトコード拡張テクノロジの適用。//やること

バイトコードの観点からは、int y = 5は単にint型変数に押し込まれ、値5が割り当てられますが、Integer x = 5はInteger.valueOf()メソッドを呼び出します。x == yは、if_icmp命令を使用して比較します。

9.7クラスのロードメカニズム、そこにあるクラスローダー、およびこれらのクラスローダーによってロードされるファイルについて説明します

Javaコードがコンパイルされると、対応するクラスファイルが生成されます。次に、java Demoコマンドを実行すると、実際にJVM仮想マシンを起動して、クラスバイトコードファイルの内容を実行しました。クラスバイトコードを実行するJVM仮想マシンのプロセスは、ロード、検証、準備、解析、初期化、使用、およびアンロードの7つの段階に分けることができます。

クラスローダーの分類

  • 1つ目:スタートアップクラス/ブートクラス:ブートストラップClassLoaderは
    C / C ++言語で実装され、JVM内にネストされており、Javaプログラムはこのクラスを直接操作できません。
    これは、JAVA_HOME / jre / lib / rt.jar、resources.jar、sun.boot.class.pathパスの下のパッケージなどのJavaコアクラスライブラリをロードするために使用され、jvm操作に必要なパッケージを提供するために使用されます。

java.lang.ClassLoaderから継承されておらず、親クラスローダーがありません

拡張クラスローダーとアプリケーションクラスローダーをロードし、それらの親クラスローダーになります

安全上の理由から、スタートアップクラスはパッケージ名で始まるクラスのみをロードします:java、javax、sun

  • 2番目のもの:拡張クラスローダー
    Java言語で記述された拡張
    クラスローダー。sun.misc.Launcher$ ExtClassLoaderによって実装されます。Javaプログラムを使用して、java.lang.ClassLoaderから派生したこのローダーを操作できます。親クラスローダーはスタートアップクラスローダーです。

システムプロパティjava.ext.dirsディレクトリからクラスライブラリをロードするか、JDKインストールディレクトリjre / lib / extディレクトリからクラスライブラリをロードします。上記のディレクトリに独自のパッケージを配置すると、自動的にロードされます。

  • 3番目:アプリケーション
    クラスローダーJava言語で記述されたアプリケーションクラスローダー。sun.misc.Launcher$ AppClassLoaderによって実装されます。
    java.lang.ClassLoaderから派生および継承された親クラスローダーは、スタートアップクラスローダーです。

これは、環境変数classpathまたはシステムプロパティjava.class.pathで指定されたパスの下にクラスライブラリをロードする役割を果たします。

これはプログラムのデフォルトのクラスローダーであり、Javaプログラムのクラスはすべてそれによってロードされます。

このローダーは、ClassLoader#getSystemClassLoader()を介して取得および操作できます。

  • 4番目:カスタムローダー
    通常の状況では、上記の3つのローダーは日常の開発作業に対応できます。満足できない場合は
    、ネットワークを使用してJavaクラスをロードするなど、ローダーをカスタマイズして、送信の安全性を確保することもできます。暗号化操作の場合、上記の3つのローダーはこのクラスをロードできません。今回は、ローダーをカスタマイズする必要があります。

9.8手書きクラスの読み込みのデモ

独自のクラスローダーを実装するには、ClassLoaderクラスを継承するだけで済みます。また、親の委任ルールを破りたい場合は、loadClassメソッドを書き直す必要があります。これは、デフォルトでは、loadClassメソッドが親の委任ルールに従うためです。

public class CustomClassLoader extends ClassLoader{

    private static final String CLASS_FILE_SUFFIX = ".class";

    //AppClassLoader的父类加载器
    private ClassLoader extClassLoader;

    public CustomClassLoader(){
        ClassLoader j = String.class.getClassLoader();
        if (j == null) {
            j = getSystemClassLoader();
            while (j.getParent() != null) {
                j = j.getParent();
            }
        }
        this.extClassLoader = j ;
    }

    protected Class<?> loadClass(String name, boolean resolve){

        Class cls = null;
        cls = findLoadedClass(name);
        if (cls != null){
            return cls;
        }
        //获取ExtClassLoader
        ClassLoader extClassLoader = getExtClassLoader() ;
        //确保自定义的类不会覆盖Java的核心类
        try {
            cls = extClassLoader.loadClass(name);
            if (cls != null){
                return cls;
            }
        }catch (ClassNotFoundException e ){

        }
        cls = findClass(name);
        return cls;
    }

    @Override
    public Class<?> findClass(String name) {
        byte[] bt = loadClassData(name);
        return defineClass(name, bt, 0, bt.length);
    }

    private byte[] loadClassData(String className) {
        // 读取Class文件呢
        InputStream is = getClass().getClassLoader().getResourceAsStream(className.replace(".", "/")+CLASS_FILE_SUFFIX);
        ByteArrayOutputStream byteSt = new ByteArrayOutputStream();
        // 写入byteStream
        int len =0;
        try {
            while((len=is.read())!=-1){
                byteSt.write(len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 转换为数组
        return byteSt.toByteArray();
    }

    public ClassLoader getExtClassLoader(){
        return extClassLoader;
    }
}


9.9オブジェクトはJavaにどのように保存されますか

Javaでは、すべてのオブジェクトがヒープに動的に割り当てられます。これはC ++とは異なります。C++オブジェクトはスタックまたはヒープのいずれかに割り当てられます。C ++では、new()を使用してオブジェクトを割り当てます。このオブジェクトはヒープに割り当てられます。グローバルまたは静的でない場合は、スタックに割り当てられます。

Javaでは、型変数を宣言する場合にのみ、参照を作成するだけです(メモリはオブジェクトに割り当てられません)。オブジェクトにメモリを割り当てるには、new()を使用する必要があります。したがって、オブジェクトは常にヒープに割り当てられます。

9.10オブジェクトヘッダー情報の内容

Javaのオブジェクト指向の考え方により、JVMには多数のストレージオブジェクトが必要です。ストレージ中にいくつかの追加機能を実現するには、オブジェクト機能を強化するためにいくつかのマークフィールドをオブジェクトに追加する必要があります。これらのマークフィールドはオブジェクトヘッダーを構成します。

1.1。通常のオブジェクト

|--------------------------------------------------------------|
|                     Object Header (64 bits)                  |
|------------------------------------|-------------------------|
|        Mark Word (32 bits)         |    Klass Word (32 bits) |
|------------------------------------|-------------------------|

1.2。配列オブジェクト

|---------------------------------------------------------------------------------|
|                                 Object Header (96 bits)                         |
|--------------------------------|-----------------------|------------------------|
|        Mark Word(32bits)       |    Klass Word(32bits) |  array length(32bits)  |
|--------------------------------|-----------------------|------------------------|

おすすめ

転載: blog.csdn.net/weixin_54707168/article/details/113975540