[セット 2] Java 面接の質問

2 番目のセット:

1.JavaScriptフロントエンド開発

1. 次のコードは何を出力しますか?

var y = 1;
if(function f(){
    
    }){
    
    
    y += typeof f;
}
console.log(y);

正解は 1undefine です。
JavaScript の if ステートメントの評価では、実際には eval 関数が使用されます。eval(function f(){}) は関数 f(){} を返しますが、これは true です。
次に、コードを同等のコードに変換します。

var k = 1;
if (1) {
    
    
    eval(function foo(){
    
    });
    k += typeof foo;
 }
console.log(k);

上記のコードの出力は実際には未定義です。どうして?eval() のドキュメントを参照すると答えが得られます。

このメソッドは、生の文字列をパラメータとしてのみ受け入れます。文字列パラメータが生の文字列でない場合、メソッドは変更されずに戻ります。

たまたま、関数 f(){} ステートメントの戻り値が unknown であるため、すべてが理にかなっています。
上のコードは以下のコードとは異なることに注意してください。

var k = 1;
if (1) {
    
    
    function foo(){
    
    };
    k += typeof foo;
 }
console.log(k); // output 1function 

2. caNum 関数を作成します。パラメータは次のように考えることができます。使用方法は次のとおりです。

Console.log(caNum(2)(3)(4)); //输出:24
Console.log(caNum(4)(3)(4)); //输出:48

最も一般的な実装バージョン:

var multiply = function () {
    
    
  var a = 1;
  for (let i = 0; i < arguments.length; i++) {
    
    
    a = a * arguments[i];
  }
  return a;
}
console.log('11:',multiply(1,2,3,4)); // 输出:24

最適化されたバージョンについて知りたい場合は、リンク: https://blog.csdn.net/qq_37268201/article/details/113262983

3. JQuery を使用して変数 obj が配列であるかどうかを判断する関数を作成します。

var arr= [1,1,1,1]
var a = '2323'
var b =  {
    
    name:'xiao',age:12}
var n = 1

1.instanceof
instanceof 演算子は、コンストラクターのプロトタイプ属性がオブジェクトのプロトタイプ チェーンのどこかに現れるかどうかを確認するために使用され、ブール値を返します。
プロトタイプ属性は変更できるため、最初に true と判断された場合でも常に true になるとは限りません。

console.log('方法1',arr instanceof Array); //如果是数组 打印结果为 true

2.
コンストラクターインスタンスのコンストラクター属性のコンストラクターはコンストラクターを指しているため、コンストラクター属性によって配列であるかどうかも判断できます。
この種の判断では、複数のグローバル環境でも問題が発生し、instanceof と同じ問題が発生します。

console.log('方法2',arr.constructor === Array);//true

3. Array.isArray() が最も推奨される方法です
。これでも正確に判定できますが、問題があります。Array.isArray() は ES5 で提案されたため、以前はこの方法がサポートされていない場合があります。 ES5。

console.log('方法3',Array.isArray(arr)); //true

function isArray(obj){
    
    
 return $.isArray(obj)
}//JQuery isArray 的实现其实就是方法5

4.
typeof がこのメソッドを使用して配列を判定すると、出力される結果は object になります (欠点は、データ型が参照データ型の場合、Object しか返せないことです)。

このメソッドの戻り値は、数値、文字列、未定義、ボリアン、オブジェクト、関数のみです。

console.log('方法4',typeof n); //number
console.log('方法4',typeof(b)) //object

5 Object.prototype.toSrtring.call()
このメソッドを使用して他のデータ型を決定する場合、注意すべき点の 1 つは、IE8 以前では、未定義と null は両方とも Object であり、IE9 以降では [object Unknown] と [object] であることです。ヌル]。

console.log(Object.prototype.toString.call(arr).indexOf('Array') !== -1); //true
console.log(Object.prototype.toString.call(arr) === '[object Array]');    //true

function isArray(obj){
    
    
 return Object.prototype.toString.call( obj ) === '[object Array]'; 
} //这里使用call来使 toString 中 this 指向 obj。进而完成判断

参考リンク:https://blog.csdn.net/qq_43399210/article/details/111403146

4. 次のコードは実行時に例外をスローします。実行できるようにコードを修正してください。

var foo = function bar(){
    
    return 12;};
typeof bar();

出力では、例外がスローされ、bar が定義されていません。コードを正常に実行したい場合は、コードを次のように変更する必要があります。

var bar = function(){
    
     return 12; };
typeof bar();

或者是

function bar(){
    
     return 12; };
typeof bar();

2. Java バックエンド開発:

1. Java でオブジェクトをシリアル化する方法と、シリアル化が必要な場合。

Serializable または Externalizable インターフェイスを実装するクラスのオブジェクトのみをバイト シーケンスにシリアル化できます。(そうでない場合は、例外がスローされます。)
送信者は Java オブジェクトをバイト シーケンスに変換してネットワーク上に送信する必要があり、他方、受信者は Java オブジェクトをバイト シーケンスから復元する必要があります。バイトシーケンス。

シリアル化: Java オブジェクトをバイト シーケンス (バイナリ) に変換するプロセス。
逆シリアル化: 一連のバイトを Java オブジェクトに復元するプロセス。

注: シリアル化は、オブジェクトの状態を維持または送信できる形式に変換するプロセスです。逆シリアル化は、ストリームをオブジェクトに変換します。これら 2 つのプロセスを組み合わせることで、データの保存と転送が簡単になります。JSON はインターフェイスのデータ交換に使用される形式です。中心となる機能は、オブジェクトの状態を保存して再構築することです。

シリアル化と逆シリアル化は通常、次の点に要約されます。

  • オブジェクトのバイト シーケンスをハード ディスク (通常はファイル) に永続的に保存します。(永続オブジェクト) オブジェクトをバイト ストリームに変換し、ハード ディスクに保存します。JVM がシャットダウンされても、バイト ストリームはそのまま残ります。ハードディスク上で次の JVM の起動を静かに待ち、シリアル化されたオブジェクトを元のオブジェクトに逆シリアル化すると、シリアル化されたバイナリ シーケンスによってストレージ領域が削減される可能性があります。

  • ネットワーク上でオブジェクトを送信する一連のバイト。(ネットワーク転送オブジェクト)

  • シリアル化を通じてプロセス間でオブジェクトを渡します。

2. 一般的に使用される Map コレクションをリストし、HashMap と HashTable の違いを簡単に説明します。

マップマッピング: 順序付けされていない一意のキー、一意でない値
ここに画像の説明を挿入します

HashMap:ハッシュ マップ/辞書、順序なし辞書、キーと値のペア データ、キーは一意、キーと値の両方を null にすることができます ハッシュテーブル: HashMap と同様、HashMap のスレッドセーフ バージョンです。スレッド同期をサポートし
ます。 , 任意 一度に Hashtable に書き込むことができるスレッドは 1 つだけであるため、Hashtale は書き込みが遅くなります。Dictionary クラスから継承されます。違いは、記録されたキーまたは値を null にすることができないこと、そして効率が低いことです。
TreeMap:赤黒ツリーによって実装されたキーと値の融合 (ソート可能) 赤黒ツリーは自己平衡二分探索ツリーです。
LinkedHashMap:リンク リスト マッピング/辞書。ハッシュマップのすべての特性を継承し、同時に要素の挿入順序を保持して二重リンク リストの特性を実装します。
ConcurrentHashMap:スレッドセーフでロック分離。ConcurrentHashMap は、これらのさまざまな部分を表すために内部的にセグメントを使用します。各セグメントは実際には小さなハッシュ テーブルであり、独自のロックを持っています。複数の変更操作は、異なるセグメントで実行される限り、同時に実行できます。

ハッシュマップとハッシュテーブルの違い:

  • HashMap は HashTable の contains メソッドを削除しますが、containsValue() メソッドと containsKey() メソッドを追加します。
  • HashTable は同期的でスレッドセーフですが、HashMap は非同期であり、hashTable よりも効率的です。
  • HashMap では空のキー値が許可されますが、hashTable では許可されません。

3. コードを記述します: Java Map トラバーサル メソッド。

マップの内容: {"名前":"張蒙蒙"、"年齢":"30"、"性別":"男性"、"コード":"3010"}

1. for ループでentrySet トラバーサルを使用すると、最も一般的に使用されるキーと値を同時に取得することもできます。

Map <String,String>map = new HashMap<String,String>();
map.put("熊大", "棕色");
map.put("熊二", "黄色");
for(Map.Entry<String, String> entry : map.entrySet()){
    
    
    String mapKey = entry.getKey();
    String mapValue = entry.getValue();
    System.out.println(mapKey+":"+mapValue);
}

2. for ループで map.keySet() を使用してキーを走査し、map.get(key) を通じて単一の値を取得するか、map.values() を使用して走査して値を取得します
。マップ内のキーまたは値のみが必要なので、entrySet を使用するよりもパフォーマンスが向上します。

Map <String,String>map = new HashMap<String,String>();
map.put("熊大", "棕色");
map.put("熊二", "黄色");
//key
for(String key : map.keySet()){
    
    
    System.out.println(key);
}
//value
for(String value : map.values()){
    
    
    System.out.println(value);
}
System.out.println("通过map.keyset进行遍历key和value");

for (String key:map.keySet()){
    
    

    System.out.println("key= "+key+" and value= "+map.get(key));

}

3. イテレータによるトラバース イテレータを
使用してトラバースする場合: foreach を使用してマップをトラバースする場合、マップのサイズを変更するとエラーが報告されますが、要素を削除するだけの場合は、イテレータの Remove メソッドを使用して要素を削除できます。

Iterator<Entry<String, String>> entries = map.entrySet().iterator();//用迭代器的时候注意:next()方法在同一循环中不能出现俩次!
//否则会抛出NoSuchElementException异常。
while(entries.hasNext()){
    
    
    Entry<String, String> entry = entries.next();
    String key = entry.getKey();
    String value = entry.getValue();
    System.out.println(key+":"+value);
}

4. キーを介して値をトラバースする (つまり、キーをトラバースする 2 番目の方法 + 値を取得する方法) は、
キー自体から値を取得する操作自体に時間がかかるため、比較的非効率的です。お勧めできません。

for(String key : map.keySet()){
    
    
    String value = map.get(key);
    System.out.println(key+":"+value);
}

いくつかの結論:
キーまたは値のみを取得したい場合は、keySet または値を使用することをお勧めします。
キーと値の両方が必要な場合は、entrySet を使用することをお勧めします。
トラバーサル プロセス中に要素を削除する必要がある場合は、 Iterator の使用を推奨します
。走査プロセス中に要素を追加する必要がある場合は、新しい一時マップを作成できます。マップには新しく追加された要素が保存されます。走査が完了すると、一時マップは元のマップに配置されます。

マップトラバーサルの参照リンク: https://blog.csdn.net/qq_44750696/article/details/112254719

4. 「リフレクション」を通じて com.weavercsd.po.UseerInfo オブジェクトのインスタンスを作成します。

リフレクションを通じてオブジェクトを作成するには、次の 2 つの方法があります。
1. Class オブジェクトの newInstance メソッドを使用して、Class オブジェクトに対応するクラス インスタンスを作成します (Class オブジェクトに対応するクラスには、デフォルトの空のコンストラクターがあります)。

Class clazz = Class.forName("com.weavercsd.po.UseerInfo");
Person person = (Person) clazz.newInstance();

2. Constructor オブジェクトの newInstance メソッドを使用して、Class オブジェクトに対応するクラス インスタンスを作成します。
このメソッドには 2 つの手順があります:
1. Class オブジェクトを通じて指定された Constructor オブジェクトを取得します。
2. Constructor オブジェクトの newInstance メソッドを呼び出して、 Classオブジェクトに対応するクラスインスタンスを作成する
このメソッドが選択可能 コンストラクターがインスタンスを作成する

Class clazz = Class.forName("com.weavercsd.po.UseerInfo");
Constructor declaredConstructor = clazz.getDeclaredConstructor(Integer.class, String.class, Integer.class, String.class);
Person person = (Person) declaredConstructor.newInstance(1, "张三", 30, "男");

Class オブジェクトの newInstance メソッドを使用します。

@Data
public class Person {
    
    

    private Integer id;
    private String name;
    private Integer age;
    private Integer sex;
}
public class TestReflectCreateObj {
    
    
    public static void main(String[] args) {
    
    
        Class clazz = null;
        try{
    
    
            clazz = Class.forName("com.kevin.base.reflect.Person");
            Person person = (Person) clazz.newInstance();
            System.out.println(person);
        }catch (ClassNotFoundException e){
    
    
            e.printStackTrace();
        } catch (InstantiationException e) {
    
    
            e.printStackTrace();
        } catch (IllegalAccessException e) {
    
    
            e.printStackTrace();
        }
    }
}

 执行结果:
 Person(id=null, name=null, age=null, sex=null)

Constructor オブジェクトの newInstance メソッドを使用します。

@Data
@AllArgsConstructor
public class Person {
    
    

    private Integer id;
    private String name;
    private Integer age;
    private String sex;
}

public class TestReflectCreateObj {
    
    
    public static void main(String[] args) {
    
    
        Class clazz = null;
        try{
    
    
            //1.获取Person类的Class对象
            clazz = Class.forName("com.kevin.base.reflect.Person");
            //2.获取构造方法并创建对象
            Constructor declaredConstructor = clazz.getDeclaredConstructor(Integer.class, String.class, Integer.class, String.class);
            //3.根据构造方法创建对象并设置属性
            Person person = (Person) declaredConstructor.newInstance(1, "张三", 30, "男");
            System.out.println(person);
        }catch (Exception e){
    
    
            e.printStackTrace();
        }
    }
}

执行结果:
Person(id=1, name=张三, age=30, sex=)

5. XML と JSON の違いは何ですか?また、解析方法は何ですか?

違い:
XML は主に要素、属性、要素コンテンツで構成されます。JSON は主にオブジェクト、配列、文​​字列、数値、ブール値 (true/false)、null で構成されます。
オブジェクト (名前と値のペアのコレクションを参照) を表すために、XML は最初に要素をオブジェクトとして使用し、各キーと値のペアは属性によって表されます。
XML では要素コンテンツの改行の処理方法を選択する必要がありますが、JSON 文字列ではこの選択を行う必要はありません。
XML にはテキストのみがあり、事前に設定された数値形式はありませんが、JSON には明確な数値形式があり、ロケールでも安全です。
XML マッピング配列には、配列要素のタグが反復的で冗長であることを除けば、大きな問題はありません。JSON の方が読みやすいです。
JSON の true/false/null は、一般的なプログラミング言語の対応するセマンティクスに簡単に統合することもできます。
XML ドキュメントには、DTD、スキーマ、および XPath などの一連の仕様を添付できます。カスタム XML 要素または属性を使用すると、さまざまな制約や関連する追加情報をデータに簡単に添付できます。データ表現機能の観点から見ると、XML は次のとおりです。 Json よりも強力ですが、多くのシナリオではそれほど複雑で重いものは必要なく、軽量で柔軟な Json が非常に人気があります。


XML: JAVA では、DOM、SAX、DOM4J、または JDOM を使用してDOM を解析してツリー構造を形成できます。これは直感的で理解しやすく、コードの作成も容易です。解析プロセス中、ツリー構造はメモリ内に保持されるため、簡単に変更できます。XML ファイルが大きいと大量のメモリを消費するため、解析パフォーマンスに影響を及ぼしやすく、メモリ オーバーフローが発生する可能性があります。
SAX は、比較的少ないメモリを消費するイベント駆動型モデルを使用します。xmI のデータのみを処理する必要がある場合に適しています。しかし、コーディングは簡単ではなく、同じ XML 内の複数の異なるデータに同時にアクセスすることは困難です。
DOM4J は、文書全体を読み取って解析する非常に優れた Java XML API であり、優れたパフォーマンス、強力な機能、非常に使いやすいという特徴を備えており、オープンソース ソフトウェアでもあります。
JDOM は、XML を処理するためのツリーベースの Java API です。ツリーをメモリにロードし、下位互換性の制限がありません。したがって、DOM よりもシンプルで高速で、欠陥が少なくなります。SAX の JAVA ルールはありますが、 JDOM は、メモリよりも大きいドキュメントを処理することを
XML ドキュメント論理モデルと呼びます。すべてのバイトが実際に変換されるという保証はありません。DTD とスキーマの実際のモデルは、インスタンス ドキュメントには提供されません。DOM 内の対応するトラバーサル パッケージはサポートされていません。
JSON: JAVA FastJSON、Gson、または Jackson を使用して解析します。
Fastjson は、Java 言語で書かれ、Alibaba によって開発された高性能 JSON プロセッサです。依存関係や追加の jar は必要なく、JDK 上で直接実行できます。FastJson は独自のアルゴリズムを使用して解析速度を極限まで高め、あらゆる json ライブラリを上回ります。
グソン現在、最も汎用性の高い Json 解析アーティファクトです。Gson は元々、Google 内部のニーズに応えて Google によって開発されました。しかし、2008 年 5 月に最初のバージョンが公開されて以来、多くの企業やユーザーによって使用されています。Gson のアプリケーションは、主に toJson と fromJson という 2 つの変換関数で構成されています。依存関係がなく、追加の jar も必要ありません。JDK 上で直接実行できます。
Jackson は、依存する jar パッケージが少なく、シンプルで使いやすく、比較的高いパフォーマンスを備えています。さらに、Jackson コミュニティは比較的活発で、更新速度も比較的速いです。Jackson では、複雑なタイプの JSON 変換 Bean で問題が発生し、一部のコレクションの Map と List の変換で問題が発生します。Jackson は複合型 Bean を Json に変換しますが、変換された json 形式は標準の Json 形式ではありません。json-lib は最も古く、最も広く使用されている json 解析ツールですが、json-lib の欠点は、多くのサードパーティ パッケージに依存していることです。

XML
拡張マークアップ言語は、インターネット データ送信のための重要なツールであり、インターネット上のあらゆるプラットフォームにまたがることができ、プログラミング言語やオペレーティング システムによって制限されません。

特徴:

  • 1.xmlはOSや言語となる開発プラットフォームとは関係ありません
  • 2. 異なるシステム間のデータ連携を実現

効果:

  1. アプリケーションの構成
  2. データインタラクション
  3. アヤックスの礎石

ルール:

  1. XML 宣言ステートメントが必要です
  2. ルート要素は 1 つだけ存在する必要があります
  3. タグでは大文字と小文字が区別されます
  4. 属性値には二重引用符を使用します
  5. タグはペアで表示されます
  6. 空のタグを閉じる
  7. 要素が正しくネストされている

JSON
はデータ交換形式です。json の正式名は JavaScript Object Notation (オブジェクト表記法を意味します) で、テキストベースで言語に依存しない軽量のデータ交換形式です。

特徴:

  1. JSON はプレーンテキストです。
  2. JSON は自己記述的で読みやすいです。
  3. JSON は階層構造になっています (値の中に値が存在します)。
  4. JSON は JavaScript 経由で解析できます。
  5. JSON データは AJAX を使用して転送できます。

JSON と XML の違い:
6. データ量の点では、XML と比較して、JSON はデータ量が小さく、送信が高速です。
7. データ対話の点では、JSON は JavaScript とより便利に対話し、解析と処理が容易です。 8.データの記述
という点では、JSON は xml よりも記述的ではありません
9. 送信速度の点では、JSON は xml よりもはるかに高速です。

JSON と XML の長所と短所:

  1. JSON は軽量で解析が簡単で、クライアントに優しい
  2. XML はさらに複雑で、DOM 番号に解析され、データを取得するためにノードをトラバースしますが、その利点は構造が明確でスケーラビリティが高いことです。

6. Restful アーキテクチャを簡単に説明し、Rest でサポートされる最も一般的に使用される HTTP リクエスト メソッドをリストします。

REST は、すべての Web アプリケーションが従うべきアーキテクチャ設計ガイドラインです。URI を使用してリソースを見つけ、HTTP (GET、POST、DELETE、PUT) を使用して操作を記述します。
REST の正式名称は Representational State Transfer で、中国語では表現 (編注: 通常は代表と訳される) 状態の転送を意味します。
RESTful は URI のアーキテクチャです。RESTful スタイルの URI を使用すると、URI が読みやすくなります。コードはよりクリーンでより論理的です。
まず第一に、RESTful アーキテクチャはリソース指向であることを理解する必要があります。各 URI はリソースを識別します。ユーザーまたはプログラマが URI を使用するとき、実際にはリソースを操作していることになります。
したがって、URI は常にリソースを中心に設計する必要があります。(URI にリソースの主キー、URI にバージョン番号を含めることができます。/ を使用してリソースの階層関係を区別し、? を使用してリソースをフィルタリングできます)

REST の最大の特徴は、リソース (クエリが必要なデータベース情報など)、統一インターフェイス (get、post、delete、put)、URI (URI はリソースのアドレスとリソースのアドレスの両方とみなすことができます) です。リソース。名前、各 URI は特定のリソースに対応します)、ステートレス (すべてのリソースは URI を通じて見つけることができ、この位置は他のリソースとは無関係であり、他のリソースの変更によって変更されることはありません)。
例: ステートフルとステートレスの違いを説明するための簡単な例を示します。たとえば、従業員の給与をクエリする場合は、システムにログインし、給与クエリ ページにアクセスし、関連する操作を実行して給与を取得する必要があります。給与をクエリする各ステップは、次の条件に依存するため、この状況はステートフルです。ワンステップ操作。前の操作が失敗する限り、後続の操作は実行できません。URL を入力して指定した従業員の給与を取得する場合、給与の取得は依存しないため、この状況はステートレスです。この場合、従業員の給与は URL に対応するリソースであり、そのリソースは HTTP の GET メソッドを通じて取得できます。これは典型的な RESTful スタイルです。REST はステートレス通信の原則に従います。これは、クライアント アプリケーションが状態を持つことができないという意味ではありません。これは、サーバーがクライアントの状態を保持すべきではないことを意味します。

RESTful アーキテクチャ:
  (1) 各 URI はリソースを表します;
  (2) このリソースの特定のプレゼンテーション層がクライアントとサーバーの間で転送されます;
  (3) クライアントは 4 つの HTTP 動詞を使用してサーバー側リソースにアクセスします。 「プレゼンテーション層の状態変換」。

2. クライアントの HTTP リクエスト メソッドは、一般的に GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS の 4 種類に分類されます。
GET はリソースの取得、 POST はリソースの作成 (リソースの更新にも使用可能)、PUT はリソースの更新、DELETE はリソースの削除です GET : リソースの取得 クライアントが GET メソッドを使用してサーバーに要求
する場合を指定すると、サーバーはリクエストに関連付けられた URI を返します。リソースの表現です。GET メソッドはサーバー上のリソースの状態を変更しないでください。GET は単にリソースにアクセスして表示します。GET 操作は安全です。

GET /users HTTP/1.1
Host: api.example.com

上記の例では、クライアントは GET メソッドを使用してすべてのユーザー情報を取得し、応答データを JSON または XML 形式で返します。
POST: リソースの作成 (リソースの更新にも使用可能)クライアントが POST メソッドを使用してサーバーにリクエストを送信すると、サーバーは新しいリソースを作成し、リソースの URI を返します。操作は安全ではありません。リクエストごとにリソースが作成されます。複数の POST リクエストを行うと、結果として複数のリソースが作成されます。
もう 1 つ注意すべき点は、作成操作では POST または PUT を使用できることです。違いは、POST はコレクション リソース (/uri) に対して操作されるのに対し、PUT 操作は特定のリソース (/uri/xxx) に対して操作されることです。一般に、URL がクライアントで決定できる場合は PUT を使用し、サーバーで決定できる場合は POST を使用します。たとえば、多くのリソースはデータベースの自動インクリメントされた主キーを識別情報として使用し、識別情報を作成しますリソースのはサーバーによってのみ提供できます。現時点では、それを使用する必要があります。

POSTPOST /users HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
    
    
  "name": "John Doe",
  "age": 30,
  "email": "[email protected]"
}

上記の例では、クライアントは POST メソッドを使用して新しいユーザーを作成し、ユーザー情報を JSON 形式でサーバーに送信します。
PUT: リソースを更新します。クライアントが PUT メソッドを使用してサーバーにリクエストを送信すると、サーバーはリクエスト URI に関連付けられたリソースの表現を更新します。データの内容を変更するために使用されますが、リソースは増加しません

PUT /users/1 HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
    
    
  "name": "John Doe",
  "age": 31,
  "email": "[email protected]"
}

上記の例では、クライアントは PUT メソッドを使用して ID 1 のユーザー情報を更新し、更新されたユーザー情報を JSON 形式でサーバーに送信します。
DELETE: リソースを削除します。クライアントが DELETE メソッドを使用してサーバーにリクエストを送信すると、サーバーはリクエスト URI に関連付けられたリソースを削除します。

DELETE /users/1 HTTP/1.1
Host: api.example.com

上記の例では、クライアントは DELETE メソッドを使用して、ID 1 のユーザー情報を削除します。
PATCH: 一部のリソースを更新するために使用されます。クライアントが PATCH メソッドを使用してサーバーにリクエストを送信すると、サーバーはリクエスト URI に関連付けられたリソースのプロパティの一部を更新します。

PATCH /users/1 HTTP/1.1
Host: api.example.com
Content-Type: application/json

{
    
    
  "age": 31
}

上記の例では、クライアントは PATCH メソッドを使用して ID 1 のユーザーの年齢情報を更新し、更新されたユーザー情報を JSON 形式でサーバーに送信します。

HEAD: リソースのメタデータを取得するために使用されますが、実際の応答本文は返されません。クライアントが HEAD メソッドを使用してサーバーにリクエストを送信すると、サーバーは、リソースのサイズや変更時間など、リクエスト URI に関連付けられたリソースに関するメタデータを返します。

HEAD /users HTTP/1.1
Host: api.example.com

上記の例では、クライアントは HEAD メソッドを使用してすべてのユーザーのメタデータを取得し、実際の応答本文を返しません。
オプション: サーバーによってサポートされている HTTP メソッドとリソースのメタデータを取得するために使用されます。クライアントが OPTIONS メソッドを使用してサーバーにリクエストを送信すると、サーバーはサポートされている HTTP メソッドと、リクエスト URI に関連付けられたリソースのメタデータを返します。

OPTIONS /users HTTP/1.1
Host: api.example.com

上記の例では、クライアントは OPTIONS メソッドを使用して、ユーザーがサポートするすべての HTTP メソッドとメタデータを取得します。

SpringBoot によって提供されるアノテーションを使用して、@RestController、@GetMapping、@PostMapping、@PutMapping、@DeleteMapping、@PathVariable アノテーションなどの RESTful Web サービスのさまざまな操作を定義します。これらのアノテーションは、RESTful Web サービスのさまざまな操作をより簡単に定義するのに役立ちます。

GET と POST の違い:

  1. GET リクエストのデータは URL に追加され (つまり、データは HTTP プロトコル ヘッダーに配置され)、URL を分割してデータを転送します。パラメータは & で接続されます (例: getCitycode?lat=100.22&lon) =35.33; POST 送信 データは HTTP パケットの本文に配置されます。
  2. ブラウザでは、GET メソッドで送信されるデータには制限があり、たとえばリクエストされた URL が長すぎてエラーが返されることがありますが、クライアントの GET リクエストであればデータ制限はありません。POST には制限がなく、より大量のデータを転送できます。
  3. POST は GET よりも安全です。ここで言うセキュリティは、上記の GET で言う「セキュリティ」とは同じ概念ではありません。上記の「セキュリティ」の意味は、単にデータを変更しないということであり、ここでのセキュリティの意味は、本当のセキュリティの意味です。例: GET 経由でデータを送信すると、ユーザー名とパスワードが URL 上に平文で表示されます。ブラウザの履歴を確認し、ログインアカウントのパスワード、検索キーワード、個人情報などのGETリクエストのパラメータを表示します。

リソース作成における POST と PUT の違いは、作成するリソースの名前 (URI) がクライアントによって決定されるかどうかです。たとえば、ブログ投稿に Java カテゴリを追加し、生成されたパスがカテゴリ名/カテゴリ/java である場合、PUT メソッドを使用できます。
PUT メソッドと POST メソッドのセマンティクスはどちらもリソースのステータスを変更することを意味するため、安全ではありません。ただし、PUT メソッドは冪等ですが、POST メソッドは冪等ではありません。この設計の理由は、HTTP プロトコルでは、POST メソッドが
リソースの状態を変更する場合、URL はリソースの親リソースを示し、ID 情報を示すと規定しているためです。変更するリソースの情報はリクエスト本文に含まれます。PUT メソッドがリソースのステータスを変更する場合、URL は変更されるリソースを直接示します。したがって、リソースを作成する場合、POST リクエストを繰り返し送信すると 2 つの異なるリソースが生成される可能性がありますが、PUT リクエストを繰り返し送信すると、URL で指定されたリソースにのみ影響します。つまり、リソースが 1 つだけ作成されます。

7. Java が Excel を読み書きする一般的な方法について説明します (テキストの説明またはコード例で回答できます)。

EasyExcel がメモリ使用量を大幅に削減できる主な理由は、Excel を解析するときにファイル データが一度にメモリに読み込まれるのではなく、データがディスクから 1 行ずつ読み込まれ、1 つずつ解析されるためです。
EasyExcel は行ごとの解析モードを採用しており、行の解析結果の処理をオブザーバー モードで通知します。

1. Java は Excel テーブルの内容を読み取ります。

  • エンティティクラス、コンバータ変換クラスを用意する
  • 主に Excel ファイル データの監視と読み取りに使用されるリスナーをインポートする準備をします。データを 1 行ずつ読み取るために使用されます。EasyExcel メソッド AnalysisEventListener を継承する必要があります。オーバーライド メソッドは 3 つあります (データ読み取り操作、ヘッダー読み取り操作) 、データ読み取り完了後の動作)
  • EasyExcel.read メソッドを使用して、読み取るファイル パス、読み取るために使用するエンティティ クラス、使用するリスナー オブジェクト、読み取るシートなどを指定します。
public class ExceListener extends AnalysisEventListener<UserData> {
    
    
    /**
     * 进行读的操作具体执行方法,一行一行的读取数据
     * 从第二行开始读取,不读取表头
     *
     * @param userData
     * @param analysisContext
     */
    @Override
    public void invoke(UserData userData, AnalysisContext analysisContext) {
    
    
        System.out.println(userData);
    }

    /**
     * 读取表头信息
     *
     * @param headMap
     * @param context
     */
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
    
    
        super.invokeHeadMap(headMap, context);
        System.out.println("表头信息:" + headMap);
    }

    /**
     * 读取完数据的操作
     *
     * @param analysisContext
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    
    
    }
}
private static void read() {
    
    
    // 指定读的路径
    String fileName = "D:\1627870562085.xlsx";
    //  调用读的方法
    EasyExcel.read(fileName, UserData.class, new ExceListener())
        .sheet().doRead();
}

2. Java を使用してデータを Excel テーブルに生成します。

  • 対応するパッケージをインポートし、エンティティクラスを作成します
  • データをエクスポートするときは、EasyExcel の write メソッドを呼び出してファイルに書き込むか、出力ストリームに書き込む必要があります。ファイルの書き込みに使用するエンティティ クラスを指定します。シートには Excel ファイルのページ シートの値を指定します。dowrite (書き込まれたデータのコレクション) )
private void writer() {
    
    
        List<UserData> userData = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
    
    
            UserData data = new UserData();
            data.setUid(i);
            data.setName("zdk" + i);
            userData.add(data);
        }
        // 指定写的路径
        String fileName = "D:\\" + System.currentTimeMillis() + ".xlsx";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,
        // 名字为模板 然后文件流会自动关闭
        EasyExcel.write(fileName, UserData.class)
                .sheet("模板")
                .doWrite(userData);
 }

8. マルチスレッドを作成するためのコーディング。(マルチスレッドを作成する 4 つの方法)

Thread クラスを継承し、Runnable インターフェイスを実装し、Callable インターフェイスとスレッド プールを実装します。

1 つ目: Thread クラスを継承します。

  1. Threadクラスを継承したサブクラスを作成する
  2. Thread クラスの run() を書き換えて、このスレッドによって実行される操作を run() 内で宣言します。
  3. Threadクラスのサブクラスのオブジェクトを作成する
  4. このオブジェクトを通じて start() を呼び出します
/**
 * 多线程的创建,方式一:继承于Threadlei
 * 1.创建一个继承于Thread类的子类
 * 2.重写Thread类的run()  将此线程执行的的操作声明在run()中
 * 3.创建Thread类的子类的对象
 * 4.通过此对象调用start()
 *
 * 例子:遍历100以内所有的偶数
 */
public class ThreadTest {
    
    
    public static void main(String[] args) {
    
    
        //3.创建Thread类的子类的对象
        MyThread myThread = new MyThread();

        //4.通过此对象调用start()  ①启动当前线程 ②调用当前线程的run()
        myThread.start();

        //不能通过myThread.run()的方式启动线程

        //再启动一个线程
        MyThread myThread1 = new MyThread();
        myThread1.start();

        //如下操作仍然是在main()线程中执行的
        for (int i = 0;i < 100 ;i++){
    
    
            if (i % 2 != 0){
    
    
                System.out.println(Thread.currentThread().getName() + ":"+"hello");
            }
        }
    }
}

//  1.创建一个继承于Thread类的子类
class MyThread extends Thread {
    
    
    //2.重写Thread类的run()
    @Override
    public void run() {
    
    
        for (int i = 0;i < 100 ;i++){
    
    
            if (i % 2 == 0){
    
    
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

2 番目のタイプ: Runnable インターフェイスを実装する

  1. Runnableインターフェースを実装するクラスを作成する
  2. Runnable に抽象メソッドを実装するクラスを実装します: run()
  3. クラスを実装するオブジェクトを作成する
  4. このオブジェクトをパラメータとして Thread クラスのコンストラクタに渡し、Thread クラスのオブジェクトを作成します。
  5. Thread クラスのオブジェクトを通じて start() を呼び出す
/**
 * 创建多线程的方式二:实现Runnable接口
 * 1.创建一个实现了Runnable接口的类
 * 2.实现类去实现Runnable中的抽象方法:run()
 * 3.创建实现类的对象
 * 4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
 * 5.通过Thread类的对象调用start()
 *
 * 比较创建线程的两种方式:
 * 开发中优先选择实现Runnable接口的方式
 * 原因:1.实现的方式没有类的单继承性的局限性
 *      2.实现的方式更适合来处理多个线程有共享数据的情况
 *
 * 联系:都实现了Runnable接口
 * 相同点:两种方式都需要重写run()方法,将线程要执行的逻辑声明在run()中
 *
 */
public class ThreadTest1 {
    
    
    public static void main(String[] args) {
    
    
        // * 3.创建实现类的对象
        MyThread myThread = new MyThread();
        // * 4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
        Thread thread1 = new Thread(myThread);
        // * 5.通过Thread类的对象调用start() ①启动线程 ②调用当前线程的run()
        thread1.start();

        Thread thread2 = new Thread(myThread);
        thread2.start();
    }
}

// * 1.创建一个实现了Runnable接口的类
class MyThread implements Runnable{
    
    
    // * 2.实现类去实现Runnable中的抽象方法:run()
    @Override
    public void run() {
    
    
        for (int i = 0; i < 100; i++) {
    
    
            if (i % 2 == 0) {
    
    
                System.out.println(Thread.currentThread().getName() + ":" + i);
            }
        }
    }
}

3 番目のタイプ: Callable インターフェイスを実装する

  1. Callableを実装する実装クラスを作成する
  2. call メソッドを実装し、このスレッドが call() で実行する必要がある操作を宣言します。
  3. Callableインターフェース実装クラスのオブジェクトを作成する
  4. Callable インターフェース実装クラスのオブジェクトをパラメータとして FutureTask コンストラクターに渡し、FutureTask のオブジェクトを作成します。
  5. FutureTask オブジェクトをパラメータとして Thread クラスのコンストラクターに渡し、Thread オブジェクトを作成し、start() メソッドを呼び出します。
  6. Callableのcallメソッドで戻り値を取得する
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * 创建线程的方式三:实现Callable接口。   JDK5.0新增
 *
 * 如何理解实现Callable接口的方式创建多线程的方式比是实现Runnable接口创建多线程方式强大
 * 1.call()可以有返回值
 * 2.call()可以抛出异常
 */
public class ThreadNew {
    
    
    public static void main(String[] args) {
    
    
        //3.创建Callable接口实现类的对象
        NumThread numThread = new NumThread();
        //4.将Callable接口实现类的对象作为参数传递到FutureTask构造器中,创建FutureTask的对象
        FutureTask futureTask = new FutureTask(numThread);


        //5.将FutureTask的对象作为参数传递到Thread类的构造器中,创建Thread对象,并调用start()方法
        Thread thread1 = new Thread(futureTask);
        thread1.start();

        try {
    
    
            //6.获取Callable中call方法中的返回值
            //get()返回值即为FutureTask构造器参数Callable实现重写的call()返回值。
            Object sum = futureTask.get();
            System.out.println(" 总和为:" + sum);

        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        } catch (ExecutionException e) {
    
    
            e.printStackTrace();
        }
    }
}

//1.创建一个实现Callable的实现类
class NumThread implements Callable{
    
    
    //2.实现call方法,将此线程需要执行的操作声明在call()中
    @Override
    public Object call() throws Exception {
    
    
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
    
    
            if(i % 2 == 0){
    
    
                System.out.println(i);
                sum += i;
            }
        }
        return sum;
    }
}

4番目の方法: スレッドプール方式

  1. 指定された数のスレッドをスレッド プールに提供します
  2. 指定したスレッドで操作を実行するには、Runnable インターフェイスまたは Callable インターフェイス実装クラスを実装するオブジェクトを提供する必要があります。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 创建线程的方式四:使用线程池
 *
 * 好处:1.提高响应速度(减少创建新线程的时间)
 *      2.降低资源消耗(重复利用线程池中的线程,不需要每次都创建)
 *      3.便于线程管理
 *
 *      corePoolSize:核心池的大小
 *      maximumPoolSize:最大线程数
 *      keepAliveTime:线程没有任务时最多保持多长时间后会终止
 */
public class ThreadPool {
    
    
    public static void main(String[] args) {
    
    
        //1.提供指定线程数量的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        ThreadPoolExecutor service1 = (ThreadPoolExecutor) executorService;
        //设置线程池的属性
        service1.setCorePoolSize(10);

        //2.执行指定线程的操作,需要提供实现Runnable接口或Callable接口实现类的对象
        executorService.execute(new NumberThread());//适合使用于Runnable
        //executorService.submit();//适合使用与Callable

        executorService.execute(new NumberThread1());

        //关闭线程池
        executorService.shutdown();
    }
}

class NumberThread implements Runnable{
    
    
    @Override
    public void run() {
    
    
        for (int i = 0; i <= 100 ; i++) {
    
    
            if(i % 2 == 0){
    
    
                System.out.println(Thread.currentThread().getName() + ":" +i);
            }

        }
    }
}

class NumberThread1 implements Runnable{
    
    
    @Override
    public void run() {
    
    
        for (int i = 0; i <= 100 ; i++) {
    
    
            if(i % 2 != 0){
    
    
                System.out.println(Thread.currentThread().getName() + ":" +i);
            }

        }
    }
}

ここに画像の説明を挿入します

9. list に格納される値は順序付けされており反復可能ですが、set に格納される値は無秩序で反復不可能です。では、set は反復不可能であるとどのような基準で判断するのでしょうか?

  1. TreeSetは最下層がTreeMapで、サブクラスはComparableインターフェイスを使って重複要素の判定を実現していますが、Setコレクション全体の特徴としては重複要素の保存ができない点が挙げられます。
  2. HashSet、最下層は HashMap、値は HashMap のキーです。要素の繰り返しの決定は、Object クラスのメソッドを使用して実装されます。
    • オブジェクトエンコーディング: public int hashCode();
    • オブジェクトの比較: public booleanquals(Object obj);

重複要素を判定する場合は、まず hashCode() でコードマッチングを行い、コードが存在しない場合はデータが存在しないことを意味し、重複がないことを証明し、コードが存在する場合は、equals() メソッドを使用してコードマッチングを行います。さらにオブジェクトを比較し、重複が見つかった場合はデータを保存できません。

Javaプログラムでは、実際の繰り返し要素の判定と処理はhashCode()とequals()の2つのメソッドで完結します。
ソート要件 (TreeSet) の場合のみ、Comparable インターフェイスを使用して実装されます。

3. データベースの知識

1. 人事テーブル: HrmResource に保存されている基本的なユーザー情報データ。SqlServer、Oracle、MySQL の 3 つの異なるデータベースを使用して項目 11 ~ 20 のデータをクエリします (注: テーブルには一意の主キー ID が含まれていますが、それらは連続していません) )

-- 1.mysql : select * from tableName where 条件 limit 当前页码*页面容量-1 , 页面容量
select * from HrmResource limit 11,10; -- MySQL   limit(起始行,每行多少页)


--2.oracle 查询20-40条记录   注:第一种方法比第二种方法效率高
第一种方法:select * from (select A.* ,rownum rn from (select * from table_name) A where rn<=40) where rn>=20;

第一种方法:select * from (select A.* ,rownum rn from (select * from table_name) A ) where rn between 20 and 40;


-- 3. sql server分页查询:  select top n <字段1>,...,<字段n> from <表名>
假设现在有这样的一张表:
 CREATE TABLE test
 (
  id int primary key not null identity,
  names varchar(20)
 )
 然后向里面插入大约1000条数据,进行分页测试
 假设页数是10,现在要拿出第5页的内容
 
 方法一:原理:拿出数据库的第5页,就是40-50条记录。首先拿出数据库中的前40条记录的id值,然后再拿出剩余部分的前10条元素
 select top 10 * from test where id not in
 (
  --40是这么计算出来的:10*(5-1)
  select top 40 id from test order by id
 )
 order by id

方法二:原理:先查询前40条记录,然后获得其最id值,如果id值为null的,那么就返回0
 然后查询id值大于前40条记录的最大id值的记录。这个查询有一个条件,就是id必须是int类型的。
select top 10 * from test where id >
 (
  select isnull(max(id),0) from 
   ( select top 40 id from test order by id ) A
 )
 order by id
 
 方法三:原理:先把表中的所有数据都按照一个rowNumber进行排序,然后查询rownuber大于40的前十条记录 
 这种方法和oracle中的一种分页方式类似,不过只支持2005版本以上的
 row_number()函数,为结果集的分区中的每一行分配一个连续的整数。
 OVER()是一个开窗函数,对集合进行聚合计算
 select top 10 * from 
 (
  select row_number() over(order by id) as rownumber,* from test
 ) A
 where rownumber > 40
 
 方法四:存储过程
1. 创建存储过程
alter procedure pageDemo
@pageSize int,
@page int
AS
declare @temp int
set @temp=@pageSize*(@page - 1)
begin
 select top (select @pageSize) * from test where id not in (select top (select @temp) id from test) order by id
end

2. 执行存储过程
exec 10,5

2. 出席およびサインイン テーブルのデータ構造は次のとおりです: テーブル名: hrmschedulesign SQL を使用してクエリを実行してください: 昨日のすべてのユーザーのサインインおよびチェックアウト時間。

ID ユーザーID 署名日 サインタイム クライアントアドレス
1 A01 2019-06-17 08:32:40 192.168.3.232
2 A01 2019-06-17 10:30:22 192.168.3.232
3 A01 2019-06-17 18:15:30 192.168.3.232
4 A02

(注: 各ユーザーの出欠シートには 1 ~ N 件のチェックイン レコードが含まれます。毎日の最も早い時刻がチェックイン データ、最も遅い時刻がチェックアウト データです。複数日にまたがる問題については必要ありません。検討します)

select userid,min(signtime) startTime,max(signtime) endTime from hrmschedulesign 
where (sysdate - to_date(signdate,'YYYY-MM-DD'))=1 group by userid;

通过where (sysdate - to_date(signdate,'YYYY-MM-DD'))=1 筛选出昨天的所有数据,
select sysdate from dual,可以得到目前系统的时间;
由于signdate不是标准的YYYY/MM/DD的形式,所以肯定不是date类型的,
因为我们在和sysdate比较的时候需要通过to_date()函数把字符串变成date类型的数据,
之后就可以比较了,得出的就是天数,对于signtime来说,可以使用min()max()进行比较,
最后在通过userid进行分组

3. 一般的なデータベースのインデックスの種類と機能を簡単に説明します。

1. 通常のインデックス (NORMAL) には
制限がありません
2. ユニークなインデックス (UNIQUE) は
キーワード値を繰り返すことができない必要があり、一意の制約が追加されます。
3. 主キーインデックス:
キーワードは重複できないか、NULL でないことが必要です。主キー制約も追加します。
4. 全文インデックス (FULLTEXT)
キーワードのソースは、すべてのフィールドのデータではなく、フィールドから抽出された特別なキーワードです。MySQL のサポートはあまり良くありません。通常、検索を完了するために elasticsearch ツールを解決するにはサードパーティの検索エンジンが使用されます。FULLTEXT は長い記事の検索に使用すると最も効果的です。比較的短いテキストに使用されます。1 行または 2 行だけであれば、通常の INDEX も使用できます。

インデックスの利点:

  • 高速クエリにより、データ取得が大幅に高速化されます。
  • 一意のインデックスを作成して、データベース テーブル内のデータの各行の一意性を確保します。
  • アクセラレータ テーブルとテーブル間の接続。
  • データの取得にグループ化句と並べ替え句を使用すると、クエリ内でのグループ化と並べ替えにかかる時間を大幅に短縮できます。

インデックスの欠点:

  • インデックスは物理スペースを占有する必要があります。追加、削除、変更の頻度がクエリの頻度よりも高い場合、インデックスの使用はお勧めできません。不必要なフィールドにインデックスを追加すると、パフォーマンスが低下します。
  • テーブル内のデータを追加、削除、変更する場合、インデックスを動的に維持する必要があるため、データのメンテナンス速度が低下します。

1) B+ インデックスとハッシュ インデックスの違い:
B+ インデックスのデータ構造は赤黒ツリー、クエリ時間の複雑さは Ologn レベル、ハッシュ インデックスの保存データ構造はハッシュ テーブル、クエリ時間は Ologn レベルです。複雑さは O(1) レベルです。はい、
B+ インデックスを使用する理由は、ハッシュが順序付けされておらず、範囲検索とソート機能をサポートしていないためです。 2
) 主キー インデックスと通常のインデックスの違い:
通常、インデックスを使用する場合主キー クエリを使用します。主キー インデックスのデータが格納されているため、そのデータ行 (innodb エンジン)、および通常のインデックス (補助インデックス) のデータには主キーが格納されており、次の方法で再度クエリする必要があります。主キー。

4. SQL を記述して、作業計画テーブルのタイトル フィールドの共通インデックスを作成します。

创建索引
create index index_name on table_name(column_name)

EX:
create index index_id on workplan(title asc)

修改表结构(添加索引)
alter table table_name add index index_name(column_name)

EX:
alter table workplan add index index_id(title asc)

创建表时,直接指定索引
create table table_name(
  id int not null,
  username varchar(64) not null,
  index [index_name] (username)  
);

删除索引
drop index [index_name] on table_name

おすすめ

転載: blog.csdn.net/m0_46459413/article/details/131955794
おすすめ