Javaインタビューの質問の全集(10)
BaiyuITハハ
91.Javaでシングルトンクラスを記述します。
回答:
- 空腹のシングルトン
public class Singleton {
private Singleton(){}
private static Singleton instance = new Singleton();
public static Singleton getInstance(){
return instance;
}
}
- 怠惰なシングルトン
public class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static synchronized Singleton getInstance(){
if (instance == null)
instance = new Singleton();
return instance;
}
}
注:シングルトンを実装するには、2つの注意事項があります。①コンストラクターをプライベートにし、外部がコンストラクターを介してオブジェクトを作成できないようにします。②パブリック静的メソッドを使用して、クラスの唯一のインスタンスを外部に返します。考えるべき質問があります:SpringのIoCコンテナは、通常のクラスのシングルトンを作成できますが、それはどのように行われますか?
92. UMLとは何ですか?
回答:UMLはUnified Modeling Language(Unified Modeling Language)の略です。1997年に発行されました。当時の既存のオブジェクト指向のモデリング言語、メソッド、プロセスを統合しています。モデリングとソフトウェアシステム開発をサポートするグラフです。ソフトウェア開発のすべての段階でモデリングと視覚化のサポートを提供します。UMLを使用すると、通信と通信を支援し、アプリケーションの設計とドキュメントの生成を支援し、システムの構造と動作を説明することもできます。
93. UMLで一般的に使用される図は何ですか?
回答:UMLは、ソフトウェアシステムの静的構造と動的構造の一部またはすべてを説明するために、さまざまなグラフィカルシンボルを定義しています。これには、ユースケース図、クラス図、シーケンス図、コラボレーションが含まれます。ダイアグラム(コラボレーションダイアグラム)、状態ダイアグラム(ステートチャートダイアグラム)、アクティビティダイアグラム(アクティビティダイアグラム)、コンポーネントダイアグラム(コンポーネントダイアグラム)、デプロイメントダイアグラム(デプロイメントダイアグラム)など。これらのグラフィカルシンボルの中で最も重要なのは、ユースケースダイアグラム(要件をキャプチャし、システムの機能モジュールとその関係をすばやく理解できるシステムの機能を説明するために使用)、クラスダイアグラム(クラスを説明する)の3つです。クラスとクラスの関係だけでなく、この図を通じてシステムをすばやく理解できます)、シーケンス図(特定のタスクを実行するときのオブジェクト間の相互作用と実行シーケンスを説明します。この図を通じて、オブジェクトが受信できるメッセージ、つまりオブジェクトを理解できます。外の世界に提供できるサービス)。
ユースケース図:
クラス図:
シーケンス図:
94.Javaでバブルソートを記述します。
回答:バブルソートはほとんどプログラマーによって作成されますが、インタビュー中に高バブルソートを作成する方法は、誰もができるわけではありません。参照コードは次のとおりです。
import java.util.Comparator;/**
* 排序器接口(策略模式: 将算法封装到具有共同接口的独立的类中使得它们可以相互替换)
*/
public interface Sorter {
/**
* 排序
* @param list 待排序的数组
*/
public <T extends Comparable<T>> void sort(T[] list); /**
* 排序
* @param list 待排序的数组
* @param comp 比较两个对象的比较器
*/
public <T> void sort(T[] list, Comparator<T> comp);
}
import java.util.Comparator;
public class BubbleSorter implements Sorter {
@Override
public <T extends Comparable<T>> void sort(T[] list) {
boolean swapped = true;
for (int i = 1, len = list.length; i < len && swapped; ++i{
swapped = false;
for (int j = 0; j < len - i; ++j) {
if (list[j].compareTo(list[j + 1]) > 0) {
T temp = list[j];
list[j] = list[j + 1];
list[j + 1] = temp;
swapped = true;
}
}
}
}
@Override
public <T> void sort(T[] list, Comparator<T> comp) {
boolean swapped = true;
for (int i = 1, len = list.length; i < len && swapped; ++i){
swapped = false;
for (int j = 0; j < len - i; ++j) {
if (comp.compare(list[j], list[j + 1]) > 0) {
T temp = list[j];
list[j] = list[j + 1];
list[j + 1] = temp;
swapped = true;
}
}
}
}
}
95.Javaでバイナリ検索を記述します。
回答:バイナリ検索は、バイナリ検索およびバイナリ検索とも呼ばれ、順序付けられた配列内の特定の要素を見つけるための検索アルゴリズムです。検索プロセスは、配列の中央の要素から開始します。中央の要素が検索対象の要素である場合、検索プロセスは終了します。特定の要素が中央の要素よりも大きいか小さい場合は、配列の半分の中央の要素よりも大きいか小さいものを検索します。 、そして最初と同じように真ん中の要素から比較を開始します。特定のステップで配列がすでに空の場合は、指定された要素が見つからないことを意味します。この検索アルゴリズムは、比較するたびに検索範囲を半分に減らし、時間の複雑さはO(logN)です。
import java.util.Comparator;
public class MyUtil {
public static <T extends Comparable<T>> int binarySearch(T[] x, T key) {
return binarySearch(x, 0, x.length- 1, key);
}
// 使用循环实现的二分查找
public static <T> int binarySearch(T[] x, T key, Comparator<T> comp) {
int low = 0;
int high = x.length - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
int cmp = comp.compare(x[mid], key);
if (cmp < 0) {
low= mid + 1;
}else if (cmp > 0) {
high= mid - 1;
}else {
return mid;
}
}
return -1;
}
// 使用递归实现的二分查找
private static<T extends Comparable<T>> int binarySearch(T[] x, int low, int high, T key) {
if(low <= high) {
int mid = low + ((high -low) >> 1);
if(key.compareTo(x[mid])== 0) {
return mid;
}else if(key.compareTo(x[mid])< 0) {
return binarySearch(x,low, mid - 1, key);
} else {
return binarySearch(x,mid + 1, high, key);
}
}
return -1;
}
}
説明:上記のコードには、2つのバージョンのバイナリ検索が示されています。1つは再帰によって実現され、もう1つはループによって実現されます。中間位置を計算するときは、(高+低)/ 2メソッドを使用しないでください。加算操作によって整数が範囲外になる可能性があるため、ここでは次の3つのメソッドのいずれかを使用する必要があります:低+(高-低)/ 2または低+ (高-低)>> 1または(低+高)>>> 1(>>>は論理的な右シフト、符号ビットなしの右シフト)
96.サーブレットとCGIの違いを説明してください。
回答:ServletとCGIの違いは、Servletがサーバープロセス内にあることです。Servletはそのservice()メソッドをマルチスレッドモードで実行します。1つのインスタンスが複数のリクエストを処理でき、そのインスタンスは通常破棄されません。ただし、CGIはリクエストごとにすべてを実行します。新しいプロセスが生成され、サービスは完了後に破棄されるため、効率はサーブレットよりも低くなります。
補足:Sun Microsystemsは、CGIと競合するために1996年にServletテクノロジーをリリースしました。Servletは特別なJavaプログラムです。JavaベースのWebアプリケーションには通常、1つ以上のServletクラスが含まれています。サーブレットは、それ自体で作成および実行することはできません。サーブレットコンテナで実行されます。コンテナは、ユーザーの要求をサーブレットプログラムに渡し、サーブレットの応答をユーザーに送り返します。通常、サーブレットは1つ以上のJSPページに関連付けられます。これまで、CGIはパフォーマンスのオーバーヘッドの問題で批判されることがよくありましたが、Fast CGIはすでにCGIの効率の問題を解決しているため、インタビュー中にCGIについて批判される必要はありません。実際、よく知っている多くのWebサイトでCGIが使用されています。技術。
97. Servletインターフェースにはどのようなメソッドがありますか?
回答:サーブレットインターフェイスは5つのメソッドを定義し、そのうち最初の3つのメソッドはサーブレットのライフサイクルに関連しています。
- void init(ServletConfig config) throws ServletException
- void service(ServletRequest req, ServletResponse resp) throws ServletException, java.io.IOException
- void destory()
- java.lang.String getServletInfo()
- ServletConfig getServletConfig()
Webコンテナがサーブレットをロードしてインスタンス化した後、サーブレットのライフサイクルが開始され、コンテナはinit()メソッドを実行してサーブレットを初期化します。リクエストが到着すると、サーブレットのservice()メソッドが呼び出され、必要に応じてservice()メソッドが呼び出されてリクエストに対応します。 doGetまたはdoPostのメソッド。サーバーが閉じられるか、プロジェクトがアンインストールされると、サーバーはServletインスタンスを破棄します。このとき、Servletのdestroy()メソッドが呼び出されます。
98.転送とリダイレクトの違いは何ですか?
回答:転送とは、コンテナ内の制御の転送です。サーバーはリソースを要求します。サーバーはターゲットアドレスのURLに直接アクセスし、そのURLの応答コンテンツを読み取ってから、コンテンツをブラウザに送信します。ブラウザはサーバーをまったく認識していません。送信されたコンテンツはどこから来たので、そのアドレスバーは元のアドレスのままです。リダイレクトとは、サーバーがロジックに基づいてステータスコードを送信し、ブラウザにそのアドレスを再度要求するように指示することを意味します。したがって、ブラウザのアドレスバーにジャンプした後、リンクアドレスを確認できます。明らかに、リダイレクトはサーバーによって保護されているリソースにアクセスできません。ただし、あるWebサイトから別のWebサイトにリダイレクトすることはできます。Forwardの方が効率的であるため、必要なときにforwardを使用してみてください(ServletRequestオブジェクトのgetRequestDispatcher()メソッドを介して取得できるRequestDispatcherオブジェクトのforward()メソッドを呼び出すことにより)。これは、実際のリンクを非表示にするのにも役立ちます。場合によっては。次に、別のサーバー上のリソースにアクセスする必要がある場合は、リダイレクトを使用する必要があります(HttpServletResponseオブジェクトによってそのsendRedirect()メソッドを呼び出すことによって実装されます)。
99. JSPの組み込みオブジェクトは何ですか?役割は何ですか?
回答:JSPには9つの組み込みオブジェクトがあります。
- request:GETまたはPOSTリクエストからのパラメータを含むクライアントのリクエストをカプセル化します。
- 応答:クライアントに対するサーバーの応答をカプセル化します。
- pageContext:他のオブジェクトはこのオブジェクトを介して取得できます。
- セッション:ユーザーセッションをカプセル化するオブジェクト。
- アプリケーション:サーバーの動作環境をカプセル化するオブジェクト。
- out:出力サーバーが応答する出力ストリームオブジェクト。
- config:Webアプリケーションの構成オブジェクト。
- ページ:JSPページ自体(Javaプログラムのこれと同等)。
- 例外:例外をスローするページをカプセル化するオブジェクト。
補足:サーブレットを使用してWebページに動的コンテンツを生成する場合、それは間違いなく非常に面倒な作業です。一方、すべてのテキストタグとHTMLタグはハードコーディングされており、わずかな変更でも再コンパイルする必要があります。JSPは、これらのServletの問題を解決します。これはServletの優れた補足です。ビュー(View)を表示するユーザーとしてのみ使用でき、コントローラー(Controller)としてのServletは、ユーザー要求の処理と特定のページへの転送またはリダイレクトを特に担当します。多くのJavaベースのWeb開発では、サーブレットとJSPの両方を使用しています。JSPページは実際にはServletであり、Servletを実行できるサーバー(Servletコンテナー)は通常、JSPページの実行環境を提供できるJSPコンテナーでもあります。TomcatはServlet / JSPコンテナーです。初めてJSPページを要求するとき、Servlet / JSPコンテナは、最初にJSPページをJSPページの実装クラスに変換します。これは、JspPageインターフェイスまたはそのサブインターフェイスHttpJspPageを実装するJavaクラスです。JspPageインターフェイスはServletのサブインターフェイスであるため、各JSPページはServletです。変換が成功すると、コンテナはServletクラスをコンパイルし、次にコンテナはJavaバイトコードをロードしてインスタンス化し、サーブレットで通常実行するライフサイクル操作を実行します。同じJSPページへの後続のリクエストでは、コンテナはJSPページが変更されているかどうかを確認し、変更されている場合は、変換、再コンパイル、および実行されます。そうでない場合は、メモリ内の既存のServletインスタンスを実行します。JSPコードの一部に対応するJavaプログラムを見ると、すべてを見ることができ、9つの組み込みオブジェクトの謎が明らかになります。
JSPページ:
<%@ page pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";
%><!DOCTYPE html><html>
<head>
<base href="<%=basePath%>">
<title>首页</title>
<style type="text/css">
* { font-family: "Arial"; }
</style>
</head>
<body>
<h1>Hello, World!</h1>
<hr/>
<h2>Current time is: <%= new java.util.Date().toString() %></h2>
</body></html>
対応するJavaコード:
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/7.0.52
* Generated at: 2014-10-13 13:28:38 UTC
* Note: The last modified time of this file was set to
* the last modified time of the source file after
* generation to assist with modification tracking.
*/package org.apache.jsp;import javax.servlet.*;import javax.servlet.http.*;import javax.servlet.jsp.*;public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
private static final javax.servlet.jsp.JspFactory _jspxFactory = javax.servlet.jsp.JspFactory
.getDefaultFactory();
private static java.util.Map<java.lang.String, java.lang.Long> _jspx_dependants;
private javax.el.ExpressionFactory _el_expressionfactory;
private org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String, java.lang.Long> getDependants() {
return _jspx_dependants;
}
public void _jspInit() {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(
getServletConfig().getServletContext()).getExpressionFactory();
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory
.getInstanceManager(getServletConfig());
}
public void _jspDestroy() {
}
public void _jspService(
final javax.servlet.http.HttpServletRequest request,
final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
// 内置对象就是在这里定义的
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html;charset=UTF-8");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write('\r');
out.write('\n');
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";// 以下代码通过输出流将HTML标签输出到浏览器中 out.write("\r\n");
out.write("\r\n");
out.write("<!DOCTYPE html>\r\n");
out.write("<html>\r\n");
out.write(" <head>\r\n");
out.write(" <base href=\"");
out.print(basePath);
out.write("\">\r\n");
out.write(" <title>首页</title>\r\n");
out.write(" <style type=\"text/css\">\r\n");
out.write(" \t* { font-family: \"Arial\"; }\r\n");
out.write(" </style>\r\n");
out.write(" </head>\r\n");
out.write(" \r\n");
out.write(" <body>\r\n");
out.write(" <h1>Hello, World!</h1>\r\n");
out.write(" <hr/>\r\n");
out.write(" <h2>Current time is: ");
out.print(new java.util.Date().toString());
out.write("</h2>\r\n");
out.write(" </body>\r\n");
out.write("</html>\r\n");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)) { out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try { out.clearBuffer();
} catch (java.io.IOException e) {
}
if (_jspx_page_context != null)
_jspx_page_context.handlePageException(t);
else
throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
100.リクエストの取得と投稿の違いは?
回答:
①getリクエストはサーバーからリソースを取得するために使用され、postはサーバーにデータを送信するために使用されます
。②getはフォーム内のデータをname = valueの形式でアクションが指すURLに追加し、両方とも「?」を使用します。接続、および各変数間の「&」接続。postは、HTTPプロトコルのリクエストヘッダーまたはメッセージ本文にデータをフォームに入れて、アクションが指すURLに渡すことです
。③getによって送信されるデータには、URLの長さ制限(1024)が適用されます。 Bytes); postは大量のデータを送信できますが、アップロードファイルは通常postメソッドを使用します;
④getを使用すると、パラメータがアドレスバーに表示されます。データが機密データでない場合はgetを使用できます。機密データの場合は引き続きアプリケーションで使用されます。 post;
⑤getはMIMEタイプapplication / x-www-form-urlencoded URLエンコーディング(パーセントサインエンコーディングとも呼ばれます)テキスト形式を使用してパラメータを渡し、送信されるパラメータが仕様に従ったテキストで構成されていることを確認します。たとえば、スペースのエンコーディングは「%20」。