深入學習java原始碼之 Array.newInstance()與Array.getLong()
深入學習java原始碼之 Array.newInstance()與Array.getLong()
Array類提供靜態方法來動態建立和訪問Java陣列。
Array允許在獲取或設定操作期間擴大轉換,但如果發生縮小轉換,則丟擲IllegalArgumentException 。
建立具有指定元件型別和長度的新陣列。 呼叫此方法相當於建立一個數組,如下所示:
int[] x = {length};
Array.newInstance(componentType, x);
方法
Modifier and Type | Method and Description |
---|---|
static Object |
get(Object array, int index) 返回指定陣列物件中的索引元件的值。 |
static boolean |
getBoolean(Object array, int index) 返回指定陣列物件中的索引元件的值,如 |
static byte |
getByte(Object array, int index) 返回指定陣列物件中的索引元件的值,如 |
static char |
getChar(Object array, int index) 返回指定陣列物件中索引元件的值,如 |
static double |
getDouble(Object array, int index) 返回指定陣列物件中的索引元件的值,如 |
static float |
getFloat(Object array, int index) 返回指定陣列物件中的索引元件的值,如 |
static int |
返回指定陣列物件中的索引元件的值,如 |
static int |
getLength(Object array) 返回指定陣列物件的長度,如 |
static long |
getLong(Object array, int index) 返回指定陣列物件中索引元件的值,如 |
static short |
getShort(Object array, int index) 返回指定陣列物件中的索引元件的值,如 |
static Object |
newInstance(類<?> componentType, int... dimensions) 建立具有指定元件型別和尺寸的新陣列。 |
static Object |
newInstance(類<?> componentType, int length) 建立具有指定元件型別和長度的新陣列。 |
static void |
set(Object array, int index, Object value) 將指定陣列物件的索引元件的值設定為指定的新值。 |
static void |
setBoolean(Object array, int index, boolean z) 將指定陣列物件的索引元件的值設定為指定的 |
static void |
setByte(Object array, int index, byte b) 將指定陣列物件的索引元件的值設定為指定的 |
static void |
setChar(Object array, int index, char c) 將指定陣列物件的索引元件的值設定為指定的 |
static void |
setDouble(Object array, int index, double d) 將指定陣列物件的索引元件的值設定為指定的 |
static void |
setFloat(Object array, int index, float f) 將指定陣列物件的索引元件的值設定為指定的 |
static void |
setInt(Object array, int index, int i) 將指定陣列物件的索引元件的值設定為指定的 |
static void |
setLong(Object array, int index, long l) 將指定陣列物件的索引元件的值設定為指定的 |
static void |
setShort(Object array, int index, short s) 將指定陣列物件的索引元件的值設定為指定的 |
java原始碼
package java.lang.reflect;
public final
class Array {
private Array() {}
public static Object newInstance(Class<?> componentType, int length)
throws NegativeArraySizeException {
return newArray(componentType, length);
}
public static Object newInstance(Class<?> componentType, int... dimensions)
throws IllegalArgumentException, NegativeArraySizeException {
return multiNewArray(componentType, dimensions);
}
public static native int getLength(Object array)
throws IllegalArgumentException;
public static native Object get(Object array, int index)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
public static native boolean getBoolean(Object array, int index)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
public static native byte getByte(Object array, int index)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
public static native char getChar(Object array, int index)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
public static native short getShort(Object array, int index)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
public static native int getInt(Object array, int index)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
public static native long getLong(Object array, int index)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
public static native float getFloat(Object array, int index)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
public static native double getDouble(Object array, int index)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
public static native void set(Object array, int index, Object value)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
public static native void setBoolean(Object array, int index, boolean z)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
public static native void setByte(Object array, int index, byte b)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
public static native void setChar(Object array, int index, char c)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
public static native void setShort(Object array, int index, short s)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
public static native void setInt(Object array, int index, int i)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
public static native void setLong(Object array, int index, long l)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
public static native void setFloat(Object array, int index, float f)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
public static native void setDouble(Object array, int index, double d)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException;
private static native Object newArray(Class<?> componentType, int length)
throws NegativeArraySizeException;
private static native Object multiNewArray(Class<?> componentType,
int[] dimensions)
throws IllegalArgumentException, NegativeArraySizeException;
}
丟擲一個應用程式嘗試建立一個負數大小的陣列。
package java.lang;
public
class NegativeArraySizeException extends RuntimeException {
private static final long serialVersionUID = -8960118058596991861L;
public NegativeArraySizeException() {
super();
}
public NegativeArraySizeException(String s) {
super(s);
}
}
丟擲表示一種方法已經通過了非法或不正確的引數。
package java.lang;
public
class IllegalArgumentException extends RuntimeException {
public IllegalArgumentException() {
super();
}
public IllegalArgumentException(String s) {
super(s);
}
public IllegalArgumentException(String message, Throwable cause) {
super(message, cause);
}
public IllegalArgumentException(Throwable cause) {
super(cause);
}
private static final long serialVersionUID = -5365630128856068164L;
}
丟擲以表示使用非法索引訪問陣列。 索引為負數或大於或等於陣列的大小。
package java.lang;
public
class ArrayIndexOutOfBoundsException extends IndexOutOfBoundsException {
private static final long serialVersionUID = -5116101128118950844L;
public ArrayIndexOutOfBoundsException() {
super();
}
public ArrayIndexOutOfBoundsException(int index) {
super("Array index out of range: " + index);
}
public ArrayIndexOutOfBoundsException(String s) {
super(s);
}
}
丟擲以表示某種索引(例如陣列,字串或向量)的索引超出範圍。
應用程式可以將此類子類化以指示類似的異常。
package java.lang;
public
class IndexOutOfBoundsException extends RuntimeException {
private static final long serialVersionUID = 234122996006267687L;
public IndexOutOfBoundsException() {
super();
}
public IndexOutOfBoundsException(String s) {
super(s);
}
}
RuntimeException是在Java虛擬機器的正常操作期間可以丟擲的那些異常的超類。
RuntimeException及其子類是未經檢查的異常 。 unchecked異常不需要在方法或建構函式的擬申報throws條款,如果他們可以通過該方法或建構函式的執行被丟擲和方法或構造邊界之外傳播。
package java.lang;
public class RuntimeException extends Exception {
static final long serialVersionUID = -7034897190745766939L;
public RuntimeException() {
super();
}
public RuntimeException(String message) {
super(message);
}
public RuntimeException(String message, Throwable cause) {
super(message, cause);
}
public RuntimeException(Throwable cause) {
super(cause);
}
protected RuntimeException(String message, Throwable cause,
boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
類異常及其子類是形式Throwable指示合理的應用程式想要捕獲的條件。
異常類和任何不是RuntimeException的子類的子類都是檢查異常 。 檢查的異常需要在方法或建構函式的throws子句中宣告,如果它們可以通過執行方法或建構函式丟擲,並在方法或建構函式邊界之外傳播。
package java.lang;
public class Exception extends Throwable {
static final long serialVersionUID = -3387516993124229948L;
public Exception() {
super();
}
public Exception(String message) {
super(message);
}
public Exception(String message, Throwable cause) {
super(message, cause);
}
public Exception(Throwable cause) {
super(cause);
}
protected Exception(String message, Throwable cause,
boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
Throwable類是Java語言中所有錯誤和異常的Throwable類。 只有作為此類(或其一個子類)的例項的物件由Java虛擬機器丟擲,或者可以由Java throw語句丟擲。 類似地,只有這個類或其子類可以是catch子句中的引數型別。 對於異常,編譯時檢查的目的Throwable和任何子類Throwable ,是不是也無論是子類RuntimeException或Error被視為檢查的異常。
通常使用兩個子類的例項Error和異常來表示出現異常情況。 通常,這些例項是在特殊情況的上下文中新建立的,以便包括相關資訊(如堆疊跟蹤資料)。
throwable在建立時包含其執行緒的執行堆疊的快照。 它還可以包含一個訊息字串,其中提供有關錯誤的更多資訊。 隨著時間的推移,一個可以丟擲的其他可拋物線可以被傳播。 最後,throwable也可能包含一個原因 :另一個可丟擲的,導致這個可丟擲的構造。 這種因果資訊的記錄被稱為連結的異常設施,因為原因本身可能有原因等等,導致“鏈”的異常,每個異常都由另一個導致。
丟擲一個原因的一個原因是丟擲它的類被構建在較低層次的抽象之上,上層的操作由於下層的故障而失敗。 讓下層投擲的投擲物向外傳播是不好的設計,因為它通常與上層提供的抽象無關。 此外,這樣做會將上層的API與其實現的細節相結合,假設較低層的異常是被檢查的異常。 丟擲“包裝異常”(即,包含原因的異常)允許上層將故障的細節傳達給其呼叫者,而不會導致這些缺點之一。 它保留了更改上層實現的靈活性,而不改變其API(特別是其方法丟擲的一組異常)。
throwable可能有一個原因的第二個原因是丟擲它的方法必須符合通用介面,該介面不允許該方法直接引用原因。 例如,假設持久集合符合Collection介面,並且其永續性在java.io頂部java.io 。 假設add方法的內部可以丟擲一個IOException 。 實施可以在細節溝通IOException同時符合它的呼叫者Collection通過封裝介面IOException在適當的未經檢查的異常。 (持久集合的規範應該表明它能夠丟擲這種異常。)
一個原因可以通過兩種方式與一個可丟擲的關聯:通過建構函式將原因作為引數,或通過initCause(Throwable)方法。 希望允許原因與他們相關聯的新的可丟擲類可以提供建構函式,這些建構函式可以引導和委派(或間接地)到Throwable函式之一的Throwable中。 因為initCause方法是公開的,它允許一個原因與任何可丟擲的,即使是“傳統的可丟擲”相關聯,其實現早於將異常連結機制新增到Throwable 。
按照慣例,類Throwable及其子類有兩個建構函式,一個不String引數,另一個String函式採用可用於生成詳細訊息的String引數。 此外,那些可能與之相關聯的原因的子類應該有兩個建構函式,一個是Throwable (原因),另一個是String (詳細資訊)和一個Throwable (原因)。
方法
Modifier and Type | Method and Description |
---|---|
void |
addSuppressed(Throwable exception) 將指定的異常附加到為了傳遞此異常而被抑制的異常。 |
Throwable |
fillInStackTrace() 填寫執行堆疊跟蹤。 |
Throwable |
getCause() 如果原因不存在或未知,則返回此throwable的原因或 |
String |
getLocalizedMessage() 建立此可丟擲的本地化描述。 |
String |
getMessage() 返回此throwable的詳細訊息字串。 |
StackTraceElement[] |
getStackTrace() 提供對 |
Throwable[] |
getSuppressed() 返回一個包含所有被抑制的異常的陣列,通常由 |
Throwable |
initCause(Throwable cause) 將此throwable的 原因初始化為指定值。 |
void |
printStackTrace() 將此throwable和其追溯列印到標準錯誤流。 |
void |
printStackTrace(PrintStream s) 將此throwable和其追溯列印到指定的列印流。 |
void |
printStackTrace(PrintWriter s) 將此throwable和其追溯列印到指定的列印作者。 |
void |
setStackTrace(StackTraceElement[] stackTrace) 設定將被返回的堆疊微量元素 |
String |
toString() 返回此可丟擲的簡短描述。 |
package java.lang;
import java.io.*;
import java.util.*;
public class Throwable implements Serializable {
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -3042686055658047285L;
private transient Object backtrace;
private String detailMessage;
private static class SentinelHolder {
public static final StackTraceElement STACK_TRACE_ELEMENT_SENTINEL =
new StackTraceElement("", "", null, Integer.MIN_VALUE);
public static final StackTraceElement[] STACK_TRACE_SENTINEL =
new StackTraceElement[] {STACK_TRACE_ELEMENT_SENTINEL};
}
private static final StackTraceElement[] UNASSIGNED_STACK = new StackTraceElement[0];
private Throwable cause = this;
private StackTraceElement[] stackTrace = UNASSIGNED_STACK;
private static final List<Throwable> SUPPRESSED_SENTINEL =
Collections.unmodifiableList(new ArrayList<Throwable>(0));
private List<Throwable> suppressedExceptions = SUPPRESSED_SENTINEL;
/** Message for trying to suppress a null exception. */
private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception.";
/** Message for trying to suppress oneself. */
private static final String SELF_SUPPRESSION_MESSAGE = "Self-suppression not permitted";
/** Caption for labeling causative exception stack traces */
private static final String CAUSE_CAPTION = "Caused by: ";
/** Caption for labeling suppressed exception stack traces */
private static final String SUPPRESSED_CAPTION = "Suppressed: ";
public Throwable() {
fillInStackTrace();
}
public Throwable(String message) {
fillInStackTrace();
detailMessage = message;
}
public Throwable(String message, Throwable cause) {
fillInStackTrace();
detailMessage = message;
this.cause = cause;
}
public Throwable(Throwable cause) {
fillInStackTrace();
detailMessage = (cause==null ? null : cause.toString());
this.cause = cause;
}
protected Throwable(String message, Throwable cause,
boolean enableSuppression,
boolean writableStackTrace) {
if (writableStackTrace) {
fillInStackTrace();
} else {
stackTrace = null;
}
detailMessage = message;
this.cause = cause;
if (!enableSuppression)
suppressedExceptions = null;
}
public String getMessage() {
return detailMessage;
}
public String getLocalizedMessage() {
return getMessage();
}
public synchronized Throwable getCause() {
return (cause==this ? null : cause);
}
public synchronized Throwable initCause(Throwable cause) {
if (this.cause != this)
throw new IllegalStateException("Can't overwrite cause with " +
Objects.toString(cause, "a null"), this);
if (cause == this)
throw new IllegalArgumentException("Self-causation not permitted", this);
this.cause = cause;
return this;
}
public String toString() {
String s = getClass().getName();
String message = getLocalizedMessage();
return (message != null) ? (s + ": " + message) : s;
}
public void printStackTrace() {
printStackTrace(System.err);
}
public void printStackTrace(PrintStream s) {
printStackTrace(new WrappedPrintStream(s));
}
private void printStackTrace(PrintStreamOrWriter s) {
// Guard against malicious overrides of Throwable.equals by
// using a Set with identity equality semantics.
Set<Throwable> dejaVu =
Collections.newSetFromMap(new IdentityHashMap<Throwable, Boolean>());
dejaVu.add(this);
synchronized (s.lock()) {
// Print our stack trace
s.println(this);
StackTraceElement[] trace = getOurStackTrace();
for (StackTraceElement traceElement : trace)
s.println("\tat " + traceElement);
// Print suppressed exceptions, if any
for (Throwable se : getSuppressed())
se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
// Print cause, if any
Throwable ourCause = getCause();
if (ourCause != null)
ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);
}
}
private void printEnclosedStackTrace(PrintStreamOrWriter s,
StackTraceElement[] enclosingTrace,
String caption,
String prefix,
Set<Throwable> dejaVu) {
assert Thread.holdsLock(s.lock());
if (dejaVu.contains(this)) {
s.println("\t[CIRCULAR REFERENCE:" + this + "]");
} else {
dejaVu.add(this);
// Compute number of frames in common between this and enclosing trace
StackTraceElement[] trace = getOurStackTrace();
int m = trace.length - 1;
int n = enclosingTrace.length - 1;
while (m >= 0 && n >=0 && trace[m].equals(enclosingTrace[n])) {
m--; n--;
}
int framesInCommon = trace.length - 1 - m;
// Print our stack trace
s.println(prefix + caption + this);
for (int i = 0; i <= m; i++)
s.println(prefix + "\tat " + trace[i]);
if (framesInCommon != 0)
s.println(prefix + "\t... " + framesInCommon + " more");
// Print suppressed exceptions, if any
for (Throwable se : getSuppressed())
se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION,
prefix +"\t", dejaVu);
// Print cause, if any
Throwable ourCause = getCause();
if (ourCause != null)
ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, prefix, dejaVu);
}
}
public void printStackTrace(PrintWriter s) {
printStackTrace(new WrappedPrintWriter(s));
}
private abstract static class PrintStreamOrWriter {
/** Returns the object to be locked when using this StreamOrWriter */
abstract Object lock();
/** Prints the specified string as a line on this StreamOrWriter */
abstract void println(Object o);
}
private static class WrappedPrintStream extends PrintStreamOrWriter {
private final PrintStream printStream;
WrappedPrintStream(PrintStream printStream) {
this.printStream = printStream;
}
Object lock() {
return printStream;
}
void println(Object o) {
printStream.println(o);
}
}
private static class WrappedPrintWriter extends PrintStreamOrWriter {
private final PrintWriter printWriter;
WrappedPrintWriter(PrintWriter printWriter) {
this.printWriter = printWriter;
}
Object lock() {
return printWriter;
}
void println(Object o) {
printWriter.println(o);
}
}
public synchronized Throwable fillInStackTrace() {
if (stackTrace != null ||
backtrace != null /* Out of protocol state */ ) {
fillInStackTrace(0);
stackTrace = UNASSIGNED_STACK;
}
return this;
}
private native Throwable fillInStackTrace(int dummy);
public StackTraceElement[] getStackTrace() {
return getOurStackTrace().clone();
}
private synchronized StackTraceElement[] getOurStackTrace() {
// Initialize stack trace field with information from
// backtrace if this is the first call to this method
if (stackTrace == UNASSIGNED_STACK ||
(stackTrace == null && backtrace != null) /* Out of protocol state */) {
int depth = getStackTraceDepth();
stackTrace = new StackTraceElement[depth];
for (int i=0; i < depth; i++)
stackTrace[i] = getStackTraceElement(i);
} else if (stackTrace == null) {
return UNASSIGNED_STACK;
}
return stackTrace;
}
public void setStackTrace(StackTraceElement[] stackTrace) {
// Validate argument
StackTraceElement[] defensiveCopy = stackTrace.clone();
for (int i = 0; i < defensiveCopy.length; i++) {
if (defensiveCopy[i] == null)
throw new NullPointerException("stackTrace[" + i + "]");
}
synchronized (this) {
if (this.stackTrace == null && // Immutable stack
backtrace == null) // Test for out of protocol state
return;
this.stackTrace = defensiveCopy;
}
}
native int getStackTraceDepth();
native StackTraceElement getStackTraceElement(int index);
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
s.defaultReadObject(); // read in all fields
if (suppressedExceptions != null) {
List<Throwable> suppressed = null;
if (suppressedExceptions.isEmpty()) {
// Use the sentinel for a zero-length list
suppressed = SUPPRESSED_SENTINEL;
} else { // Copy Throwables to new list
suppressed = new ArrayList<>(1);
for (Throwable t : suppressedExceptions) {
// Enforce constraints on suppressed exceptions in
// case of corrupt or malicious stream.
if (t == null)
throw new NullPointerException(NULL_CAUSE_MESSAGE);
if (t == this)
throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE);
suppressed.add(t);
}
}
suppressedExceptions = suppressed;
} // else a null suppressedExceptions field remains null
if (stackTrace != null) {
if (stackTrace.length == 0) {
stackTrace = UNASSIGNED_STACK.clone();
} else if (stackTrace.length == 1 &&
// Check for the marker of an immutable stack trace
SentinelHolder.STACK_TRACE_ELEMENT_SENTINEL.equals(stackTrace[0])) {
stackTrace = null;
} else { // Verify stack trace elements are non-null.
for(StackTraceElement ste : stackTrace) {
if (ste == null)
throw new NullPointerException("null StackTraceElement in serial stream. ");
}
}
} else {
stackTrace = UNASSIGNED_STACK.clone();
}
}
private synchronized void writeObject(ObjectOutputStream s)
throws IOException {
// Ensure that the stackTrace field is initialized to a
// non-null value, if appropriate. As of JDK 7, a null stack
// trace field is a valid value indicating the stack trace
// should not be set.
getOurStackTrace();
StackTraceElement[] oldStackTrace = stackTrace;
try {
if (stackTrace == null)
stackTrace = SentinelHolder.STACK_TRACE_SENTINEL;
s.defaultWriteObject();
} finally {
stackTrace = oldStackTrace;
}
}
public final synchronized void addSuppressed(Throwable exception) {
if (exception == this)
throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE, exception);
if (exception == null)
throw new NullPointerException(NULL_CAUSE_MESSAGE);
if (suppressedExceptions == null) // Suppressed exceptions not recorded
return;
if (suppressedExceptions == SUPPRESSED_SENTINEL)
suppressedExceptions = new ArrayList<>(1);
suppressedExceptions.add(exception);
}
private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0];
public final synchronized Throwable[] getSuppressed() {
if (suppressedExceptions == SUPPRESSED_SENTINEL ||
suppressedExceptions == null)
return EMPTY_THROWABLE_ARRAY;
else
return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
}
}