zoukankan      html  css  js  c++  java
  • Java Exception & RTTI

    Exception

     1 Try
     2 { 
     3        ... ...
     4 } 
     5 catch (Exception ex)
     6 {
     7     …; 
     8    throw new Throwable(ex); 
     9 }
    10 catch (Throwable ex)
    11 {
    12    …;
    13 }
    14 finally
    15 {
    16 
    17 }
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 package java.lang;
     19 
     20 import java.io.IOException;
     21 import java.io.ObjectInputStream;
     22 import java.io.ObjectOutputStream;
     23 import java.io.PrintStream;
     24 import java.io.PrintWriter;
     25 import java.util.ArrayList;
     26 import java.util.List;
     27 import libcore.util.EmptyArray;
     28 
     29 /**
     30  * The superclass of all classes which can be thrown by the VM. The
     31  * two direct subclasses are recoverable exceptions ({@code Exception}) and
     32  * unrecoverable errors ({@code Error}). This class provides common methods for
     33  * accessing a string message which provides extra information about the
     34  * circumstances in which the {@code Throwable} was created (basically an error
     35  * message in most cases), and for saving a stack trace (that is, a record of
     36  * the call stack at a particular point in time) which can be printed later.
     37  * <p>
     38  * A {@code Throwable} can also include a cause, which is a nested {@code
     39  * Throwable} that represents the original problem that led to this {@code
     40  * Throwable}. It is often used for wrapping various types of errors into a
     41  * common {@code Throwable} without losing the detailed original error
     42  * information. When printing the stack trace, the trace of the cause is
     43  * included.
     44  *
     45  * @see Error
     46  * @see Exception
     47  * @see RuntimeException
     48  */
     49 public class Throwable implements java.io.Serializable {
     50     private static final long serialVersionUID = -3042686055658047285L;
     51 
     52     /**
     53      * The message provided when the exception was created.
     54      */
     55     private String detailMessage;
     56 
     57     /**
     58      * The cause of this Throwable. Null when there is no cause.
     59      */
     60     private Throwable cause = this;
     61 
     62     /**
     63      * Throwables suppressed by this throwable. Null when suppressed exceptions
     64      * are disabled.
     65      */
     66     private List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
     67 
     68     /**
     69      * An intermediate representation of the stack trace.  This field may
     70      * be accessed by the VM; do not rename.
     71      */
     72     private volatile Object stackState;
     73 
     74     /**
     75      * A fully-expanded representation of the stack trace.
     76      */
     77     private StackTraceElement[] stackTrace;
     78 
     79     /**
     80      * Constructs a new {@code Throwable} that includes the current stack trace.
     81      */
     82     public Throwable() {
     83         fillInStackTrace();
     84     }
     85 
     86     /**
     87      * Constructs a new {@code Throwable} with the current stack trace and the
     88      * specified detail message.
     89      *
     90      * @param detailMessage
     91      *            the detail message for this {@code Throwable}.
     92      */
     93     public Throwable(String detailMessage) {
     94         this();
     95         this.detailMessage = detailMessage;
     96     }
     97 
     98     /**
     99      * Constructs a new {@code Throwable} with the current stack trace, the
    100      * specified detail message and the specified cause.
    101      *
    102      * @param detailMessage
    103      *            the detail message for this {@code Throwable}.
    104      * @param throwable
    105      *            the cause of this {@code Throwable}.
    106      */
    107     public Throwable(String detailMessage, Throwable throwable) {
    108         this();
    109         this.detailMessage = detailMessage;
    110         cause = throwable;
    111     }
    112 
    113     /**
    114      * Constructs a new {@code Throwable} with the current stack trace and the
    115      * specified cause.
    116      *
    117      * @param throwable
    118      *            the cause of this {@code Throwable}.
    119      */
    120     public Throwable(Throwable throwable) {
    121         this();
    122         this.detailMessage = throwable == null ? null : throwable.toString();
    123         cause = throwable;
    124     }
    125 
    126     /**
    127      * Constructs a new {@code Throwable} with the current stack trace, the
    128      * specified detail message and the specified cause.
    129      *
    130      * @param enableSuppression if false, throwables passed to {@link
    131      *     #addSuppressed(Throwable)} will be silently discarded.
    132      * @since 1.7
    133      * @hide 1.7
    134      */
    135     protected Throwable(String detailMessage, Throwable throwable, boolean enableSuppression) {
    136         this(detailMessage, throwable);
    137         if (!enableSuppression) {
    138             this.suppressedExceptions = null;
    139         }
    140     }
    141 
    142     /**
    143      * Records the stack trace from the point where this method has been called
    144      * to this {@code Throwable}. This method is invoked by the {@code Throwable} constructors.
    145      *
    146      * <p>This method is public so that code (such as an RPC system) which catches
    147      * a {@code Throwable} and then re-throws it can replace the construction-time stack trace
    148      * with a stack trace from the location where the exception was re-thrown, by <i>calling</i>
    149      * {@code fillInStackTrace}.
    150      *
    151      * <p>This method is non-final so that non-Java language implementations can disable VM stack
    152      * traces for their language. Filling in the stack trace is relatively expensive.
    153      * <i>Overriding</i> this method in the root of a language's exception hierarchy allows the
    154      * language to avoid paying for something it doesn't need.
    155      *
    156      * @return this {@code Throwable} instance.
    157      */
    158     public Throwable fillInStackTrace() {
    159         // Fill in the intermediate representation
    160         stackState = nativeFillInStackTrace();
    161         // Mark the full representation as empty
    162         stackTrace = null;
    163         return this;
    164     }
    165 
    166     /**
    167      * Returns the extra information message which was provided when this
    168      * {@code Throwable} was created. Returns {@code null} if no message was
    169      * provided at creation time.
    170      *
    171      * @return this {@code Throwable}'s detail message.
    172      */
    173     public String getMessage() {
    174         return detailMessage;
    175     }
    176 
    177     /**
    178      * Returns the extra information message which was provided when this
    179      * {@code Throwable} was created. Returns {@code null} if no message was
    180      * provided at creation time. Subclasses may override this method to return
    181      * localized text for the message. Android returns the regular detail message.
    182      *
    183      * @return this {@code Throwable}'s localized detail message.
    184      */
    185     public String getLocalizedMessage() {
    186         return getMessage();
    187     }
    188 
    189     /**
    190      * Returns the array of stack trace elements of this {@code Throwable}. Each
    191      * {@code StackTraceElement} represents an entry in the call stack. The
    192      * element at position 0 is the top of the stack, that is, the stack frame
    193      * where this {@code Throwable} is thrown.
    194      *
    195      * @return a copy of the array of {@code StackTraceElement}s representing
    196      *         the call stack. Changes in the array obtained from this call will
    197      *         not change the call stack stored in this {@code Throwable}.
    198      * @see #printStackTrace()
    199      */
    200     public StackTraceElement[] getStackTrace() {
    201         return getInternalStackTrace().clone();
    202     }
    203 
    204     /**
    205      * Sets the array of stack trace elements. Each {@code StackTraceElement}
    206      * represents an entry in the call stack. A copy of the specified array is
    207      * stored in this {@code Throwable}. will be returned by {@code
    208      * getStackTrace()} and printed by {@code printStackTrace()}.
    209      *
    210      * @param trace
    211      *            the new array of {@code StackTraceElement}s. A copy of the
    212      *            array is stored in this {@code Throwable}, so subsequent
    213      *            changes to {@code trace} will not change the call stack stored
    214      *            in this {@code Throwable}.
    215      * @throws NullPointerException
    216      *             if any element in {@code trace} is {@code null}.
    217      * @see #printStackTrace()
    218      */
    219     public void setStackTrace(StackTraceElement[] trace) {
    220         StackTraceElement[] newTrace = trace.clone();
    221         for (StackTraceElement element : newTrace) {
    222             if (element == null) {
    223                 throw new NullPointerException();
    224             }
    225         }
    226         stackTrace = newTrace;
    227     }
    228 
    229     /**
    230      * Writes a printable representation of this {@code Throwable}'s stack trace
    231      * to the {@code System.err} stream.
    232      *
    233      */
    234     public void printStackTrace() {
    235         printStackTrace(System.err);
    236     }
    237 
    238     /**
    239      * Counts the number of duplicate stack frames, starting from the
    240      * end of the stack.
    241      *
    242      * @param currentStack a stack to compare
    243      * @param parentStack a stack to compare
    244      *
    245      * @return the number of duplicate stack frames.
    246      */
    247     private static int countDuplicates(StackTraceElement[] currentStack,
    248             StackTraceElement[] parentStack) {
    249         int duplicates = 0;
    250         int parentIndex = parentStack.length;
    251         for (int i = currentStack.length; --i >= 0 && --parentIndex >= 0;) {
    252             StackTraceElement parentFrame = parentStack[parentIndex];
    253             if (parentFrame.equals(currentStack[i])) {
    254                 duplicates++;
    255             } else {
    256                 break;
    257             }
    258         }
    259         return duplicates;
    260     }
    261 
    262     /**
    263      * Returns an array of StackTraceElement. Each StackTraceElement
    264      * represents a entry on the stack.
    265      *
    266      * @return an array of StackTraceElement representing the stack
    267      */
    268     private StackTraceElement[] getInternalStackTrace() {
    269         if (stackTrace == null) {
    270             stackTrace = nativeGetStackTrace(stackState);
    271             stackState = null; // Clean up intermediate representation
    272         }
    273         return stackTrace;
    274     }
    275 
    276     /**
    277      * Writes a printable representation of this {@code Throwable}'s stack trace
    278      * to the specified print stream. If the {@code Throwable} contains a
    279      * {@link #getCause() cause}, the method will be invoked recursively for
    280      * the nested {@code Throwable}.
    281      *
    282      * @param err
    283      *            the stream to write the stack trace on.
    284      */
    285     public void printStackTrace(PrintStream err) {
    286         try {
    287             printStackTrace(err, "", null);
    288         } catch (IOException e) {
    289             // Appendable.append throws IOException but PrintStream.append doesn't.
    290             throw new AssertionError();
    291         }
    292     }
    293 
    294     /**
    295      * Writes a printable representation of this {@code Throwable}'s stack trace
    296      * to the specified print writer. If the {@code Throwable} contains a
    297      * {@link #getCause() cause}, the method will be invoked recursively for the
    298      * nested {@code Throwable}.
    299      *
    300      * @param err
    301      *            the writer to write the stack trace on.
    302      */
    303     public void printStackTrace(PrintWriter err) {
    304         try {
    305             printStackTrace(err, "", null);
    306         } catch (IOException e) {
    307             // Appendable.append throws IOException, but PrintWriter.append doesn't.
    308             throw new AssertionError();
    309         }
    310     }
    311 
    312     /**
    313      * @param indent additional indentation on each line of the stack trace.
    314      *     This is the empty string for all but suppressed throwables.
    315      * @param parentStack the parent stack trace to suppress duplicates from, or
    316      *     null if this stack trace has no parent.
    317      */
    318     private void printStackTrace(Appendable err, String indent, StackTraceElement[] parentStack)
    319             throws IOException {
    320         err.append(toString());
    321         err.append("
    ");
    322 
    323         StackTraceElement[] stack = getInternalStackTrace();
    324         if (stack != null) {
    325             int duplicates = parentStack != null ? countDuplicates(stack, parentStack) : 0;
    326             for (int i = 0; i < stack.length - duplicates; i++) {
    327                 err.append(indent);
    328                 err.append("	at ");
    329                 err.append(stack[i].toString());
    330                 err.append("
    ");
    331             }
    332 
    333             if (duplicates > 0) {
    334                 err.append(indent);
    335                 err.append("	... ");
    336                 err.append(Integer.toString(duplicates));
    337                 err.append(" more
    ");
    338             }
    339         }
    340 
    341         // Print suppressed exceptions indented one level deeper.
    342         if (suppressedExceptions != null) {
    343             for (Throwable throwable : suppressedExceptions) {
    344                 err.append(indent);
    345                 err.append("	Suppressed: ");
    346                 throwable.printStackTrace(err, indent + "	", stack);
    347             }
    348         }
    349 
    350         Throwable cause = getCause();
    351         if (cause != null) {
    352             err.append(indent);
    353             err.append("Caused by: ");
    354             cause.printStackTrace(err, indent, stack);
    355         }
    356     }
    357 
    358     @Override
    359     public String toString() {
    360         String msg = getLocalizedMessage();
    361         String name = getClass().getName();
    362         if (msg == null) {
    363             return name;
    364         }
    365         return name + ": " + msg;
    366     }
    367 
    368     /**
    369      * Initializes the cause of this {@code Throwable}. The cause can only be
    370      * initialized once.
    371      *
    372      * @param throwable
    373      *            the cause of this {@code Throwable}.
    374      * @return this {@code Throwable} instance.
    375      * @throws IllegalArgumentException
    376      *             if {@code Throwable} is this object.
    377      * @throws IllegalStateException
    378      *             if the cause has already been initialized.
    379      */
    380     public Throwable initCause(Throwable throwable) {
    381         if (cause != this) {
    382             throw new IllegalStateException("Cause already initialized");
    383         }
    384         if (throwable == this) {
    385             throw new IllegalArgumentException("throwable == this");
    386         }
    387         cause = throwable;
    388         return this;
    389     }
    390 
    391     /**
    392      * Returns the cause of this {@code Throwable}, or {@code null} if there is
    393      * no cause.
    394      *
    395      * @return Throwable this {@code Throwable}'s cause.
    396      */
    397     public Throwable getCause() {
    398         if (cause == this) {
    399             return null;
    400         }
    401         return cause;
    402     }
    403 
    404     /**
    405      * Adds {@code throwable} to the list of throwables suppressed by this. The
    406      * throwable will included when this exception's stack trace is printed.
    407      *
    408      * @throws IllegalArgumentException if {@code throwable == this}.
    409      * @throws NullPointerException if {@code throwable == null}.
    410      * @since 1.7
    411      * @hide 1.7
    412      */
    413     public final void addSuppressed(Throwable throwable) {
    414         if (throwable == this) {
    415             throw new IllegalArgumentException("suppressed == this");
    416         }
    417         if (throwable == null) {
    418             throw new NullPointerException("suppressed == null");
    419         }
    420         if (suppressedExceptions != null) {
    421             suppressedExceptions.add(throwable);
    422         }
    423     }
    424 
    425     /**
    426      * Returns the throwables suppressed by this.
    427      *
    428      * @since 1.7
    429      * @hide 1.7
    430      */
    431     public final Throwable[] getSuppressed() {
    432         return (suppressedExceptions != null)
    433                 ? suppressedExceptions.toArray(new Throwable[suppressedExceptions.size()])
    434                 : EmptyArray.THROWABLE;
    435     }
    436 
    437     private void writeObject(ObjectOutputStream out) throws IOException {
    438         // ensure the stackTrace field is initialized
    439         getInternalStackTrace();
    440         out.defaultWriteObject();
    441     }
    442 
    443     private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    444         in.defaultReadObject();
    445 
    446         if (suppressedExceptions != null) {
    447             // the deserialized list may be unmodifiable, so just create a mutable copy
    448             suppressedExceptions = new ArrayList<Throwable>(suppressedExceptions);
    449         }
    450     }
    451 
    452     /*
    453      * Creates a compact, VM-specific collection of goodies, suitable for
    454      * storing in the "stackState" field, based on the current thread's
    455      * call stack.
    456      */
    457     private static native Object nativeFillInStackTrace();
    458 
    459     /*
    460      * Creates an array of StackTraceElement objects from the data held
    461      * in "stackState".
    462      */
    463     private static native StackTraceElement[] nativeGetStackTrace(Object stackState);
    464 }
    View Code
     1 /*
     2  *  Licensed to the Apache Software Foundation (ASF) under one or more
     3  *  contributor license agreements.  See the NOTICE file distributed with
     4  *  this work for additional information regarding copyright ownership.
     5  *  The ASF licenses this file to You under the Apache License, Version 2.0
     6  *  (the "License"); you may not use this file except in compliance with
     7  *  the License.  You may obtain a copy of the License at
     8  *
     9  *     http://www.apache.org/licenses/LICENSE-2.0
    10  *
    11  *  Unless required by applicable law or agreed to in writing, software
    12  *  distributed under the License is distributed on an "AS IS" BASIS,
    13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  *  See the License for the specific language governing permissions and
    15  *  limitations under the License.
    16  */
    17 
    18 package java.lang;
    19 
    20 
    21 /**
    22  * {@code Exception} is the superclass of all classes that represent recoverable
    23  * exceptions. When exceptions are thrown, they may be caught by application
    24  * code.
    25  *
    26  * @see Throwable
    27  * @see Error
    28  * @see RuntimeException
    29  */
    30 public class Exception extends Throwable {
    31     private static final long serialVersionUID = -3387516993124229948L;
    32 
    33     /**
    34      * Constructs a new {@code Exception} that includes the current stack trace.
    35      */
    36     public Exception() {
    37     }
    38 
    39     /**
    40      * Constructs a new {@code Exception} with the current stack trace and the
    41      * specified detail message.
    42      *
    43      * @param detailMessage
    44      *            the detail message for this exception.
    45      */
    46     public Exception(String detailMessage) {
    47         super(detailMessage);
    48     }
    49 
    50     /**
    51      * Constructs a new {@code Exception} with the current stack trace, the
    52      * specified detail message and the specified cause.
    53      *
    54      * @param detailMessage
    55      *            the detail message for this exception.
    56      * @param throwable
    57      *            the cause of this exception.
    58      */
    59     public Exception(String detailMessage, Throwable throwable) {
    60         super(detailMessage, throwable);
    61     }
    62 
    63     /**
    64      * Constructs a new {@code Exception} with the current stack trace and the
    65      * specified cause.
    66      *
    67      * @param throwable
    68      *            the cause of this exception.
    69      */
    70     public Exception(Throwable throwable) {
    71         super(throwable);
    72     }
    73 }
    View Code
    1. Java的基本原理就是“形式错误的代码不会运行”。
    2. 与C++类似,捕获错误最理想的是在编译期间,最好在试图运行程序以前。
    3. “违例条件”表示在出现什么问题的时候应中止方法或作用域的继续。为了将违例条件与普通问题区分开,违例条件是非常重要的一个因素。而在违例条件的情况下,却无法继续下去,因为当地没有提供解决问题所需的足够多的信息。此时,我们能做的唯一事情就是跳出当地环境,将那个问题委托给一个更高级的负责人。这便是出现违例时出现的情况。
    4. 首先,按照与创建Java对象一样的方法创建违例对象:在内存“堆”里,使用new来创建。随后,停止当前执行路径(记住不可沿这条路径继续下去),然后从当前的环境中释放出违例对象的句柄。此时,违例控制机制会接管一切,并开始查找一个恰当的地方,用于继续程序的执行。这个恰当的地方便是“违例控制器”,它的职责是从问题中恢复,使程序要么尝试另一条执行路径,要么简单地继续。
    5. 和Java的其他任何对象一样,需要用new在内存堆里创建违例,并需调用一个构建器。在所有标准违例中,存在着两个构建器:第一个是默认构建器,第二个则需使用一个字串自变量,使我们能在违例里置入相关信息.
    6. 若某个方法产生一个违例,必须保证该违例能被捕获,并获得正确对待。对于Java的违例控制机制,它的一个好处就是允许我们在一个地方将精力集中在要解决的问题上,然后在另一个地方对待来自那个代码内部的错误。
    7. 若位于一个方法内部,并“掷”出一个违例(或在这个方法内部调用的另一个方法产生了违例),那个方法就会在违例产生过程中退出。若不想一个throw离开方法,可在那个方法内部设置一个特殊的代码块,用它捕获违例。这就叫作“try块”,因为要在这个地方“尝试”各种方法调用。try块属于一种普通的作用域,用一个try关键字开头:
      try {// 可能产生违例的代码}
    8. 当然,生成的违例必须在某个地方中止。这个“地方”便是违例控制器或者违例控制模块。而且针对想捕获的每种违例类型,都必须有一个相应的违例控制器。违例控制器紧接在try块后面,且用catch(捕获)关键字标记。
    9. 控制器必须“紧接”在try块后面。若“掷”出一个违例,违例控制机制就会搜寻自变量与违例类型相符的第一个控制器。随后,它会进入那个catch从句,并认为违例已得到控制(一旦catch从句结束,对控制器的搜索也会停止)。只有相符的catch从句才会得到执行;它与switch语句不同,后者在每个case后都需要一个break命令,防止误执行其他语句。在try块内部,请注意大量不同的方法调用可能生成相同的违例,但只需要一个控制器。
    10. 违例规范采用了一个额外的关键字:throws;后面跟随全部潜在的违例类型。
    11. 假若方法造成了一个违例,但没有对其进行控制,编译器会侦测到这个情况,并告诉我们必须控制违例,或者指出应该从方法里“掷”出一个违例规范。通过坚持从顶部到底部排列违例规范,Java可在编译期保证违例的正确性(注释②)。
    12. 我们可创建一个控制器,令其捕获所有类型的违例。具体的做法是捕获基础类违例类型Exception(也存在其他类型的基础违例,但Exception是适用于几乎所有编程活动的基础)。
    13. 在某些情况下,我们想重新掷出刚才产生过的违例,特别是在用Exception捕获所有可能的违例时。由于我们已拥有当前违例的句柄,所以只需简单地重新掷出那个句柄即可. 重新“掷”出一个违例导致违例进入更高一级环境的违例控制器中。用于同一个try块的任何更进一步的catch从句仍然会被忽略。此外,与违例对象有关的所有东西都会得到保留,所以用于捕获特定违例类型的更高一级的控制器可以从那个对象里提取出所有信息。
    14. Throwable类必须在违例规格中出现,因为fillInStackTrace()会生成一个Throwable对象的句柄。由于Throwable是Exception的一个基础类,所以有可能获得一个能够“掷”出的对象(具有Throwable属性),但却并非一个Exception(违例)。因此,在main()中用于Exception的句柄可能丢失自己的目标。为保证所有东西均井然有序,编译器强制Throwable使用一个违例规范。
    15. Java包含了一个名为Throwable的类,它对可以作为违例“掷”出的所有东西进行了描述。Throwable对象有两种常规类型(亦即“从Throwable继承”)。其中,Error代表编译期和系统错误,我们一般不必特意捕获它们(除在特殊情况以外)。Exception是可以从任何标准Java库的类方法中“掷”出的基本类型。此外,它们亦可从我们自己的方法以及运行期偶发事件中“掷”出。
    16. 由于编译器并不强制违例规范捕获它们,所以假如不捕获的话,一个RuntimeException可能过滤掉我们到达main()方法的所有途径。
    17. 假若一个RuntimeException获得到达main()的所有途径,同时不被捕获,那么当程序退出时,会为那个违例调用printStackTrace()。注意也许能在自己的代码中仅忽略RuntimeException,因为编译器已正确实行了其他所有控制。因为RuntimeException在此时代表一个编程错误:(1) 一个我们不能捕获的错误(例如,由客户程序员接收传递给自己方法的一个空句柄)。(2) 作为一名程序员,一个应在自己的代码中检查的错误(如ArrayIndexOutOfBoundException,此时应注意数组的大小)。
    18. 为创建自己的违例类,必须从一个现有的违例类型继承——最好在含义上与新违例近似。在第二个构建器中,通过使用super关键字,明确调用了带有一个String参数的基础类构建器。
    19. 覆盖一个方法时,只能产生已在方法的基础类版本中定义的违例。这是一个重要的限制,因为它意味着与基础类协同工作的代码也会自动应用于从基础类衍生的任何对象(当然,这属于基本的OOP概念),其中包括违例。
    20. C++施加了类似的限制,要求衍生方法违例与基础类方法掷出的违例相同,或者从后者衍生。在这种情况下,C++实际上能够在编译期间检查违例规范。
    21. 尽管违例规范是由编译器在继承期间强行遵守的,但违例规范并不属于方法类型的一部分,后者仅包括了方法名以及自变量类型。因此,我们不可在违例规范的基础上覆盖方法。除此以外,尽管违例规范存在于一个方法的基础类版本中,但并不表示它必须在方法的衍生类版本中存在。这与方法的“继承”颇有不同(进行继承时,基础类中的方法也必须在衍生类中存在)。换言之,用于一个特定方法的“违例规范接口”可能在继承和覆盖时变得更“窄”,但它不会变得更“宽”——这与继承时的类接口规则是正好相反的。
    22. 无论一个违例是否在try块中发生,我们经常都想执行一些特定的代码。对一些特定的操作,经常都会遇到这种情况,但在恢复内存时一般都不需要(因为垃圾收集器会自动照料一切)。为达到这个目的,可在所有违例控制器的末尾使用一个finally从句(注释④)。
    23. 在没有“垃圾收集”以及“自动调用破坏器”机制的一种语言中(注释⑤),finally显得特别重要,因为程序员可用它担保内存的正确释放——无论在try块内部发生了什么状况。但Java提供了垃圾收集机制,所以内存的释放几乎绝对不会成为问题。另外,它也没有构建器可供调用。
    24. “破坏器”(Destructor)是“构建器”(Constructor)的反义词。它代表一个特殊的函数,一旦某个对象失去用处,通常就会调用它。我们肯定知道在哪里以及何时调用破坏器。C++提供了自动的破坏器调用机制,但Delphi的Object Pascal版本1及2却不具备这一能力(在这种语言中,破坏器的含义与用法都发生了变化)。
    25. “掷”出一个违例后,违例控制系统会按当初编写的顺序搜索“最接近”的控制器。一旦找到相符的控制器,就认为违例已得到控制,不再进行更多的搜索工作。在违例和它的控制器之间,并不需要非常精确的匹配。一个衍生类对象可与基础类的一个控制器相配.
    26. 用违例做下面这些事情:
      (1) 解决问题并再次调用造成违例的方法。
      (2) 平息事态的发展,并在不重新尝试方法的前提下继续。
      (3) 计算另一些结果,而不是希望方法产生的结果。
      (4) 在当前环境中尽可能解决问题,以及将相同的违例重新“掷”出一个更高级的环境。
      (5) 在当前环境中尽可能解决问题,以及将不同的违例重新“掷”出一个更高级的环境。
      (6) 中止程序执行。
      (7) 简化编码。若违例方案使事情变得更加复杂,那就会令人非常烦恼,不如不用。
      (8) 使自己的库和程序变得更加安全。这既是一种“短期投资”(便于调试),也是一种“长期投资”(改善应用程序的健壮性)

    RTTI = Running-Time Type Identification      

    Class

       1 /*
       2  * Licensed to the Apache Software Foundation (ASF) under one or more
       3  * contributor license agreements.  See the NOTICE file distributed with
       4  * this work for additional information regarding copyright ownership.
       5  * The ASF licenses this file to You under the Apache License, Version 2.0
       6  * (the "License"); you may not use this file except in compliance with
       7  * the License.  You may obtain a copy of the License at
       8  *
       9  *     http://www.apache.org/licenses/LICENSE-2.0
      10  *
      11  * Unless required by applicable law or agreed to in writing, software
      12  * distributed under the License is distributed on an "AS IS" BASIS,
      13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14  * See the License for the specific language governing permissions and
      15  * limitations under the License.
      16  */
      17 /*
      18  * Copyright (C) 2006-2007 The Android Open Source Project
      19  *
      20  * Licensed under the Apache License, Version 2.0 (the "License");
      21  * you may not use this file except in compliance with the License.
      22  * You may obtain a copy of the License at
      23  *
      24  *      http://www.apache.org/licenses/LICENSE-2.0
      25  *
      26  * Unless required by applicable law or agreed to in writing, software
      27  * distributed under the License is distributed on an "AS IS" BASIS,
      28  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      29  * See the License for the specific language governing permissions and
      30  * limitations under the License.
      31  */
      32 
      33 package java.lang;
      34 
      35 import dalvik.system.VMStack;
      36 import java.io.InputStream;
      37 import java.io.Serializable;
      38 import java.lang.annotation.Annotation;
      39 import java.lang.annotation.Inherited;
      40 import java.lang.reflect.AnnotatedElement;
      41 import java.lang.reflect.Constructor;
      42 import java.lang.reflect.Field;
      43 import java.lang.reflect.GenericDeclaration;
      44 import java.lang.reflect.Member;
      45 import java.lang.reflect.Method;
      46 import java.lang.reflect.Modifier;
      47 import java.lang.reflect.Type;
      48 import java.lang.reflect.TypeVariable;
      49 import java.net.URL;
      50 import java.security.ProtectionDomain;
      51 import java.util.ArrayList;
      52 import java.util.Arrays;
      53 import java.util.Collection;
      54 import java.util.HashMap;
      55 import java.util.List;
      56 import libcore.util.CollectionUtils;
      57 import libcore.util.EmptyArray;
      58 import org.apache.harmony.kernel.vm.StringUtils;
      59 import org.apache.harmony.luni.lang.reflect.GenericSignatureParser;
      60 import org.apache.harmony.luni.lang.reflect.Types;
      61 
      62 /**
      63  * The in-memory representation of a Java class. This representation serves as
      64  * the starting point for querying class-related information, a process usually
      65  * called "reflection". There are basically three types of {@code Class}
      66  * instances: those representing real classes and interfaces, those representing
      67  * primitive types, and those representing array classes.
      68  *
      69  * <h4>Class instances representing object types (classes or interfaces)</h4>
      70  * <p>
      71  * These represent an ordinary class or interface as found in the class
      72  * hierarchy. The name associated with these {@code Class} instances is simply
      73  * the fully qualified class name of the class or interface that it represents.
      74  * In addition to this human-readable name, each class is also associated by a
      75  * so-called <em>signature</em>, which is the letter "L", followed by the
      76  * class name and a semicolon (";"). The signature is what the runtime system
      77  * uses internally for identifying the class (for example in a DEX file).
      78  * </p>
      79  * <h4>Classes representing primitive types</h4>
      80  * <p>
      81  * These represent the standard Java primitive types and hence share their
      82  * names (for example "int" for the {@code int} primitive type). Although it is
      83  * not possible to create new instances based on these {@code Class} instances,
      84  * they are still useful for providing reflection information, and as the
      85  * component type of array classes. There is one {@code Class} instance for each
      86  * primitive type, and their signatures are:
      87  * </p>
      88  * <ul>
      89  * <li>{@code B} representing the {@code byte} primitive type</li>
      90  * <li>{@code S} representing the {@code short} primitive type</li>
      91  * <li>{@code I} representing the {@code int} primitive type</li>
      92  * <li>{@code J} representing the {@code long} primitive type</li>
      93  * <li>{@code F} representing the {@code float} primitive type</li>
      94  * <li>{@code D} representing the {@code double} primitive type</li>
      95  * <li>{@code C} representing the {@code char} primitive type</li>
      96  * <li>{@code Z} representing the {@code boolean} primitive type</li>
      97  * <li>{@code V} representing void function return values</li>
      98  * </ul>
      99  * <p>
     100  * <h4>Classes representing array classes</h4>
     101  * <p>
     102  * These represent the classes of Java arrays. There is one such {@code Class}
     103  * instance per combination of array leaf component type and arity (number of
     104  * dimensions). In this case, the name associated with the {@code Class}
     105  * consists of one or more left square brackets (one per dimension in the array)
     106  * followed by the signature of the class representing the leaf component type,
     107  * which can be either an object type or a primitive type. The signature of a
     108  * {@code Class} representing an array type is the same as its name. Examples
     109  * of array class signatures are:
     110  * </p>
     111  * <ul>
     112  * <li>{@code [I} representing the {@code int[]} type</li>
     113  * <li>{@code [Ljava/lang/String;} representing the {@code String[]} type</li>
     114  * <li>{@code [[[C} representing the {@code char[][][]} type (three dimensions!)</li>
     115  * </ul>
     116  */
     117 public final class Class<T> implements Serializable, AnnotatedElement, GenericDeclaration, Type {
     118 
     119     private static final long serialVersionUID = 3206093459760846163L;
     120 
     121     /**
     122      * Lazily computed name of this class; always prefer calling getName().
     123      */
     124     private transient String name;
     125 
     126     private Class() {
     127         // Prevent this class to be instantiated, instance
     128         // should be created by JVM only
     129     }
     130 
     131     /**
     132      * Get the Signature attribute for this class.  Returns null if not found.
     133      */
     134     private String getSignatureAttribute() {
     135         Object[] annotation = getSignatureAnnotation();
     136 
     137         if (annotation == null) {
     138             return null;
     139         }
     140 
     141         return StringUtils.combineStrings(annotation);
     142     }
     143 
     144     /**
     145      * Get the Signature annotation for this class.  Returns null if not found.
     146      */
     147     native private Object[] getSignatureAnnotation();
     148 
     149     /**
     150      * Returns a {@code Class} object which represents the class with the
     151      * specified name. The name should be the name of a class as described in
     152      * the {@link Class class definition}; however, {@code Class}es representing
     153      * primitive types can not be found using this method.
     154      * <p>
     155      * If the class has not been loaded so far, it is being loaded and linked
     156      * first. This is done through either the class loader of the calling class
     157      * or one of its parent class loaders. The class is also being initialized,
     158      * which means that a possible static initializer block is executed.
     159      *
     160      * @param className
     161      *            the name of the non-primitive-type class to find.
     162      * @return the named {@code Class} instance.
     163      * @throws ClassNotFoundException
     164      *             if the requested class can not be found.
     165      * @throws LinkageError
     166      *             if an error occurs during linkage
     167      * @throws ExceptionInInitializerError
     168      *             if an exception occurs during static initialization of a
     169      *             class.
     170      */
     171     public static Class<?> forName(String className) throws ClassNotFoundException {
     172         return forName(className, true, VMStack.getCallingClassLoader());
     173     }
     174 
     175     /**
     176      * Returns a {@code Class} object which represents the class with the
     177      * specified name. The name should be the name of a class as described in
     178      * the {@link Class class definition}, however {@code Class}es representing
     179      * primitive types can not be found using this method. Security rules will
     180      * be obeyed.
     181      * <p>
     182      * If the class has not been loaded so far, it is being loaded and linked
     183      * first. This is done through either the specified class loader or one of
     184      * its parent class loaders. The caller can also request the class to be
     185      * initialized, which means that a possible static initializer block is
     186      * executed.
     187      *
     188      * @param className
     189      *            the name of the non-primitive-type class to find.
     190      * @param initializeBoolean
     191      *            indicates whether the class should be initialized.
     192      * @param classLoader
     193      *            the class loader to use to load the class.
     194      * @return the named {@code Class} instance.
     195      * @throws ClassNotFoundException
     196      *             if the requested class can not be found.
     197      * @throws LinkageError
     198      *             if an error occurs during linkage
     199      * @throws ExceptionInInitializerError
     200      *             if an exception occurs during static initialization of a
     201      *             class.
     202      */
     203     public static Class<?> forName(String className, boolean initializeBoolean,
     204             ClassLoader classLoader) throws ClassNotFoundException {
     205 
     206         if (classLoader == null) {
     207             classLoader = ClassLoader.getSystemClassLoader();
     208         }
     209         // Catch an Exception thrown by the underlying native code. It wraps
     210         // up everything inside a ClassNotFoundException, even if e.g. an
     211         // Error occurred during initialization. This as a workaround for
     212         // an ExceptionInInitilaizerError that's also wrapped. It is actually
     213         // expected to be thrown. Maybe the same goes for other errors.
     214         // Not wrapping up all the errors will break android though.
     215         Class<?> result;
     216         try {
     217             result = classForName(className, initializeBoolean,
     218                     classLoader);
     219         } catch (ClassNotFoundException e) {
     220             Throwable cause = e.getCause();
     221             if (cause instanceof ExceptionInInitializerError) {
     222                 throw (ExceptionInInitializerError) cause;
     223             }
     224             throw e;
     225         }
     226         return result;
     227     }
     228 
     229     /*
     230      * Returns a class by name without any security checks.
     231      *
     232      * @param className The name of the non-primitive type class to find
     233      * @param initializeBoolean A boolean indicating whether the class should be
     234      *        initialized
     235      * @param classLoader The class loader to use to load the class
     236      * @return the named class.
     237      * @throws ClassNotFoundException If the class could not be found
     238      */
     239     static native Class<?> classForName(String className, boolean initializeBoolean,
     240             ClassLoader classLoader) throws ClassNotFoundException;
     241 
     242     /**
     243      * Returns an array containing {@code Class} objects for all public classes
     244      * and interfaces that are members of this class. This includes public
     245      * members inherited from super classes and interfaces. If there are no such
     246      * class members or if this object represents a primitive type then an array
     247      * of length 0 is returned.
     248      *
     249      * @return the public class members of the class represented by this object.
     250      */
     251     public Class<?>[] getClasses() {
     252         return getFullListOfClasses(true);
     253     }
     254 
     255     @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
     256         if (annotationType == null) {
     257             throw new NullPointerException("annotationType == null");
     258         }
     259 
     260         A annotation = getDeclaredAnnotation(annotationType);
     261         if (annotation != null) {
     262             return annotation;
     263         }
     264 
     265         if (annotationType.isAnnotationPresent(Inherited.class)) {
     266             for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
     267                 annotation = sup.getDeclaredAnnotation(annotationType);
     268                 if (annotation != null) {
     269                     return annotation;
     270                 }
     271             }
     272         }
     273 
     274         return null;
     275     }
     276 
     277     /**
     278      * Returns all the annotations of this class. If there are no annotations
     279      * then an empty array is returned.
     280      *
     281      * @return a copy of the array containing this class' annotations.
     282      * @see #getDeclaredAnnotations()
     283      */
     284     public Annotation[] getAnnotations() {
     285         /*
     286          * We need to get the annotations declared on this class, plus the
     287          * annotations from superclasses that have the "@Inherited" annotation
     288          * set.  We create a temporary map to use while we accumulate the
     289          * annotations and convert it to an array at the end.
     290          *
     291          * It's possible to have duplicates when annotations are inherited.
     292          * We use a Map to filter those out.
     293          *
     294          * HashMap might be overkill here.
     295          */
     296         HashMap<Class, Annotation> map = new HashMap<Class, Annotation>();
     297         Annotation[] declaredAnnotations = getDeclaredAnnotations();
     298 
     299         for (int i = declaredAnnotations.length-1; i >= 0; --i) {
     300             map.put(declaredAnnotations[i].annotationType(), declaredAnnotations[i]);
     301         }
     302         for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
     303             declaredAnnotations = sup.getDeclaredAnnotations();
     304             for (int i = declaredAnnotations.length-1; i >= 0; --i) {
     305                 Class<?> clazz = declaredAnnotations[i].annotationType();
     306                 if (!map.containsKey(clazz) && clazz.isAnnotationPresent(Inherited.class)) {
     307                     map.put(clazz, declaredAnnotations[i]);
     308                 }
     309             }
     310         }
     311 
     312         /* convert annotation values from HashMap to array */
     313         Collection<Annotation> coll = map.values();
     314         return coll.toArray(new Annotation[coll.size()]);
     315     }
     316 
     317     /**
     318      * Returns the canonical name of this class. If this class does not have a
     319      * canonical name as defined in the Java Language Specification, then the
     320      * method returns {@code null}.
     321      *
     322      * @return this class' canonical name, or {@code null} if it does not have a
     323      *         canonical name.
     324      */
     325     public String getCanonicalName() {
     326         if (isLocalClass() || isAnonymousClass())
     327             return null;
     328 
     329         if (isArray()) {
     330             /*
     331              * The canonical name of an array type depends on the (existence of)
     332              * the component type's canonical name.
     333              */
     334             String name = getComponentType().getCanonicalName();
     335             if (name != null) {
     336                 return name + "[]";
     337             }
     338         } else if (isMemberClass()) {
     339             /*
     340              * The canonical name of an inner class depends on the (existence
     341              * of) the declaring class' canonical name.
     342              */
     343             String name = getDeclaringClass().getCanonicalName();
     344             if (name != null) {
     345                 return name + "." + getSimpleName();
     346             }
     347         } else {
     348             /*
     349              * The canonical name of a top-level class or primitive type is
     350              * equal to the fully qualified name.
     351              */
     352             return getName();
     353         }
     354 
     355         /*
     356          * Other classes don't have a canonical name.
     357          */
     358         return null;
     359     }
     360 
     361     /**
     362      * Returns the class loader which was used to load the class represented by
     363      * this {@code Class}. Implementations are free to return {@code null} for
     364      * classes that were loaded by the bootstrap class loader. The Android
     365      * reference implementation, though, returns a reference to an actual
     366      * representation of the bootstrap class loader.
     367      *
     368      * @return the class loader for the represented class.
     369      * @see ClassLoader
     370      */
     371     public ClassLoader getClassLoader() {
     372         if (this.isPrimitive()) {
     373             return null;
     374         }
     375 
     376         ClassLoader loader = getClassLoaderImpl();
     377         if (loader == null) {
     378             loader = BootClassLoader.getInstance();
     379         }
     380         return loader;
     381     }
     382 
     383     /**
     384      * This must be provided by the VM vendor, as it is used by other provided
     385      * class implementations in this package. Outside of this class, it is used
     386      * by SecurityManager.classLoaderDepth(),
     387      * currentClassLoader() and currentLoadedClass(). Return the ClassLoader for
     388      * this Class without doing any security checks. The bootstrap ClassLoader
     389      * is returned, unlike getClassLoader() which returns null in place of the
     390      * bootstrap ClassLoader.
     391      *
     392      * @return the ClassLoader
     393      */
     394     ClassLoader getClassLoaderImpl() {
     395         ClassLoader loader = getClassLoader(this);
     396         return loader == null ? BootClassLoader.getInstance() : loader;
     397     }
     398 
     399     /*
     400      * Returns the defining class loader for the given class.
     401      *
     402      * @param clazz the class the class loader of which we want
     403      * @return the class loader
     404      */
     405     private static native ClassLoader getClassLoader(Class<?> clazz);
     406 
     407     /**
     408      * Returns a {@code Class} object which represents the component type if
     409      * this class represents an array type. Returns {@code null} if this class
     410      * does not represent an array type. The component type of an array type is
     411      * the type of the elements of the array.
     412      *
     413      * @return the component type of this class.
     414      */
     415     public native Class<?> getComponentType();
     416 
     417     /**
     418      * Returns a {@code Constructor} object which represents the public
     419      * constructor matching the specified parameter types.
     420      *
     421      * @param parameterTypes
     422      *            the parameter types of the requested constructor.
     423      *            {@code (Class[]) null} is equivalent to the empty array.
     424      * @return the constructor described by {@code parameterTypes}.
     425      * @throws NoSuchMethodException
     426      *             if the constructor can not be found.
     427      * @see #getDeclaredConstructor(Class[])
     428      */
     429     @SuppressWarnings("unchecked")
     430     public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException {
     431         return (Constructor) getConstructorOrMethod("<init>", false, true, parameterTypes);
     432     }
     433 
     434     /**
     435      * Returns a constructor or method with the specified name.
     436      *
     437      * @param name the method name, or "<init>" to return a constructor.
     438      * @param recursive true to search supertypes.
     439      */
     440     private Member getConstructorOrMethod(String name, boolean recursive,
     441             boolean publicOnly, Class<?>[] parameterTypes) throws NoSuchMethodException {
     442         if (recursive && !publicOnly) {
     443             throw new AssertionError(); // can't lookup non-public members recursively
     444         }
     445         if (name == null) {
     446             throw new NullPointerException("name == null");
     447         }
     448         if (parameterTypes == null) {
     449             parameterTypes = EmptyArray.CLASS;
     450         }
     451         for (Class<?> c : parameterTypes) {
     452             if (c == null) {
     453                 throw new NoSuchMethodException("parameter type is null");
     454             }
     455         }
     456         Member result = recursive
     457                 ? getPublicConstructorOrMethodRecursive(name, parameterTypes)
     458                 : Class.getDeclaredConstructorOrMethod(this, name, parameterTypes);
     459         if (result == null || publicOnly && (result.getModifiers() & Modifier.PUBLIC) == 0) {
     460             throw new NoSuchMethodException(name + " " + Arrays.toString(parameterTypes));
     461         }
     462         return result;
     463     }
     464 
     465     private Member getPublicConstructorOrMethodRecursive(String name, Class<?>[] parameterTypes) {
     466         // search superclasses
     467         for (Class<?> c = this; c != null; c = c.getSuperclass()) {
     468             Member result = Class.getDeclaredConstructorOrMethod(c, name, parameterTypes);
     469             if (result != null && (result.getModifiers() & Modifier.PUBLIC) != 0) {
     470                 return result;
     471             }
     472         }
     473 
     474         // search implemented interfaces
     475         for (Class<?> c = this; c != null; c = c.getSuperclass()) {
     476             for (Class<?> ifc : c.getInterfaces()) {
     477                 Member result = ifc.getPublicConstructorOrMethodRecursive(name, parameterTypes);
     478                 if (result != null && (result.getModifiers() & Modifier.PUBLIC) != 0) {
     479                     return result;
     480                 }
     481             }
     482         }
     483 
     484         return null;
     485     }
     486 
     487     /**
     488      * Returns an array containing {@code Constructor} objects for all public
     489      * constructors for the class represented by this {@code Class}. If there
     490      * are no public constructors or if this {@code Class} represents an array
     491      * class, a primitive type or void then an empty array is returned.
     492      *
     493      * @return an array with the public constructors of the class represented by
     494      *         this {@code Class}.
     495      * @see #getDeclaredConstructors()
     496      */
     497     public Constructor<?>[] getConstructors() {
     498         return getDeclaredConstructors(this, true);
     499     }
     500 
     501     /**
     502      * Returns the annotations that are directly defined on the class
     503      * represented by this {@code Class}. Annotations that are inherited are not
     504      * included in the result. If there are no annotations at all, an empty
     505      * array is returned.
     506      *
     507      * @return a copy of the array containing the annotations defined for the
     508      *         class that this {@code Class} represents.
     509      * @see #getAnnotations()
     510      */
     511     native public Annotation[] getDeclaredAnnotations();
     512 
     513     /**
     514      * Returns the annotation if it exists.
     515      */
     516     native private <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass);
     517 
     518     /**
     519      * Returns true if the annotation exists.
     520      */
     521     native private boolean isDeclaredAnnotationPresent(Class<? extends Annotation> annotationClass);
     522 
     523     /**
     524      * Returns an array containing {@code Class} objects for all classes and
     525      * interfaces that are declared as members of the class which this {@code
     526      * Class} represents. If there are no classes or interfaces declared or if
     527      * this class represents an array class, a primitive type or void, then an
     528      * empty array is returned.
     529      *
     530      * @return an array with {@code Class} objects for all the classes and
     531      *         interfaces that are used in member declarations.
     532      */
     533     public Class<?>[] getDeclaredClasses() {
     534         return getDeclaredClasses(this, false);
     535     }
     536 
     537     /*
     538      * Returns the list of member classes without performing any security checks
     539      * first. This includes the member classes inherited from superclasses. If no
     540      * member classes exist at all, an empty array is returned.
     541      *
     542      * @param publicOnly reflects whether we want only public members or all of them
     543      * @return the list of classes
     544      */
     545     private Class<?>[] getFullListOfClasses(boolean publicOnly) {
     546         Class<?>[] result = getDeclaredClasses(this, publicOnly);
     547 
     548         // Traverse all superclasses
     549         Class<?> clazz = this.getSuperclass();
     550         while (clazz != null) {
     551             Class<?>[] temp = getDeclaredClasses(clazz, publicOnly);
     552             if (temp.length != 0) {
     553                 result = arraycopy(new Class[result.length + temp.length], result, temp);
     554             }
     555 
     556             clazz = clazz.getSuperclass();
     557         }
     558 
     559         return result;
     560     }
     561 
     562     /*
     563      * Returns the list of member classes of the given class. No security checks
     564      * are performed. If no members exist, an empty array is returned.
     565      *
     566      * @param clazz the class the members of which we want
     567      * @param publicOnly reflects whether we want only public member or all of them
     568      * @return the class' class members
     569      */
     570     private static native Class<?>[] getDeclaredClasses(Class<?> clazz, boolean publicOnly);
     571 
     572     /**
     573      * Returns a {@code Constructor} object which represents the constructor
     574      * matching the specified parameter types that is declared by the class
     575      * represented by this {@code Class}.
     576      *
     577      * @param parameterTypes
     578      *            the parameter types of the requested constructor.
     579      *            {@code (Class[]) null} is equivalent to the empty array.
     580      * @return the constructor described by {@code parameterTypes}.
     581      * @throws NoSuchMethodException
     582      *             if the requested constructor can not be found.
     583      * @see #getConstructor(Class[])
     584      */
     585     @SuppressWarnings("unchecked")
     586     public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
     587             throws NoSuchMethodException {
     588         return (Constructor) getConstructorOrMethod("<init>", false, false, parameterTypes);
     589     }
     590 
     591     /**
     592      * Returns an array containing {@code Constructor} objects for all
     593      * constructors declared in the class represented by this {@code Class}. If
     594      * there are no constructors or if this {@code Class} represents an array
     595      * class, a primitive type or void then an empty array is returned.
     596      *
     597      * @return an array with the constructors declared in the class represented
     598      *         by this {@code Class}.
     599      * @see #getConstructors()
     600      */
     601     public Constructor<?>[] getDeclaredConstructors() {
     602         return getDeclaredConstructors(this, false);
     603     }
     604 
     605     /*
     606      * Returns the list of constructors without performing any security checks
     607      * first. If no constructors exist, an empty array is returned.
     608      *
     609      * @param clazz the class of interest
     610      * @param publicOnly reflects whether we want only public constructors or all of them
     611      * @return the list of constructors
     612      */
     613     private static native <T> Constructor<T>[] getDeclaredConstructors(
     614             Class<T> clazz, boolean publicOnly);
     615 
     616     /**
     617      * Returns a {@code Field} object for the field with the specified name
     618      * which is declared in the class represented by this {@code Class}.
     619      *
     620      * @param name the name of the requested field.
     621      * @return the requested field in the class represented by this class.
     622      * @throws NoSuchFieldException if the requested field can not be found.
     623      * @see #getField(String)
     624      */
     625     public Field getDeclaredField(String name) throws NoSuchFieldException {
     626         if (name == null) {
     627             throw new NullPointerException("name == null");
     628         }
     629         Field result = getDeclaredField(this, name);
     630         if (result == null) {
     631             throw new NoSuchFieldException(name);
     632         }
     633         return result;
     634     }
     635 
     636     /**
     637      * Returns an array containing {@code Field} objects for all fields declared
     638      * in the class represented by this {@code Class}. If there are no fields or
     639      * if this {@code Class} represents an array class, a primitive type or void
     640      * then an empty array is returned.
     641      *
     642      * @return an array with the fields declared in the class represented by
     643      *         this class.
     644      * @see #getFields()
     645      */
     646     public Field[] getDeclaredFields() {
     647         return getDeclaredFields(this, false);
     648     }
     649 
     650     /*
     651      * Returns the list of fields without performing any security checks
     652      * first. If no fields exist at all, an empty array is returned.
     653      *
     654      * @param clazz the class of interest
     655      * @param publicOnly reflects whether we want only public fields or all of them
     656      * @return the list of fields
     657      */
     658     static native Field[] getDeclaredFields(Class<?> clazz, boolean publicOnly);
     659 
     660     /**
     661      * Returns the field if it is defined by {@code clazz}; null otherwise. This
     662      * may return a non-public member.
     663      */
     664     static native Field getDeclaredField(Class<?> clazz, String name);
     665 
     666     /**
     667      * Returns a {@code Method} object which represents the method matching the
     668      * specified name and parameter types that is declared by the class
     669      * represented by this {@code Class}.
     670      *
     671      * @param name
     672      *            the requested method's name.
     673      * @param parameterTypes
     674      *            the parameter types of the requested method.
     675      *            {@code (Class[]) null} is equivalent to the empty array.
     676      * @return the method described by {@code name} and {@code parameterTypes}.
     677      * @throws NoSuchMethodException
     678      *             if the requested constructor can not be found.
     679      * @throws NullPointerException
     680      *             if {@code name} is {@code null}.
     681      * @see #getMethod(String, Class[])
     682      */
     683     public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
     684             throws NoSuchMethodException {
     685         Member member = getConstructorOrMethod(name, false, false, parameterTypes);
     686         if (member instanceof Constructor) {
     687             throw new NoSuchMethodException(name);
     688         }
     689         return (Method) member;
     690     }
     691 
     692     /**
     693      * Returns an array containing {@code Method} objects for all methods
     694      * declared in the class represented by this {@code Class}. If there are no
     695      * methods or if this {@code Class} represents an array class, a primitive
     696      * type or void then an empty array is returned.
     697      *
     698      * @return an array with the methods declared in the class represented by
     699      *         this {@code Class}.
     700      * @see #getMethods()
     701      */
     702     public Method[] getDeclaredMethods() {
     703         return getDeclaredMethods(this, false);
     704     }
     705 
     706     /**
     707      * Returns the list of methods without performing any security checks
     708      * first. If no methods exist, an empty array is returned.
     709      */
     710     static native Method[] getDeclaredMethods(Class<?> clazz, boolean publicOnly);
     711 
     712     /**
     713      * Returns the constructor or method if it is defined by {@code clazz}; null
     714      * otherwise. This may return a non-public member.
     715      *
     716      * @param name the method name, or "<init>" to get a constructor.
     717      */
     718     static native Member getDeclaredConstructorOrMethod(Class clazz, String name, Class[] args);
     719 
     720     /**
     721      * Returns the declaring {@code Class} of this {@code Class}. Returns
     722      * {@code null} if the class is not a member of another class or if this
     723      * {@code Class} represents an array class, a primitive type or void.
     724      *
     725      * @return the declaring {@code Class} or {@code null}.
     726      */
     727     native public Class<?> getDeclaringClass();
     728 
     729     /**
     730      * Returns the enclosing {@code Class} of this {@code Class}. If there is no
     731      * enclosing class the method returns {@code null}.
     732      *
     733      * @return the enclosing {@code Class} or {@code null}.
     734      */
     735     native public Class<?> getEnclosingClass();
     736 
     737     /**
     738      * Gets the enclosing {@code Constructor} of this {@code Class}, if it is an
     739      * anonymous or local/automatic class; otherwise {@code null}.
     740      *
     741      * @return the enclosing {@code Constructor} instance or {@code null}.
     742      */
     743     native public Constructor<?> getEnclosingConstructor();
     744 
     745     /**
     746      * Gets the enclosing {@code Method} of this {@code Class}, if it is an
     747      * anonymous or local/automatic class; otherwise {@code null}.
     748      *
     749      * @return the enclosing {@code Method} instance or {@code null}.
     750      */
     751     native public Method getEnclosingMethod();
     752 
     753     /**
     754      * Gets the {@code enum} constants associated with this {@code Class}.
     755      * Returns {@code null} if this {@code Class} does not represent an {@code
     756      * enum} type.
     757      *
     758      * @return an array with the {@code enum} constants or {@code null}.
     759      */
     760     @SuppressWarnings("unchecked") // we only cast after confirming that this class is an enum
     761     public T[] getEnumConstants() {
     762         if (!isEnum()) {
     763             return null;
     764         }
     765         return (T[]) Enum.getSharedConstants((Class) this).clone();
     766     }
     767 
     768     /**
     769      * Returns a {@code Field} object which represents the public field with the
     770      * specified name. This method first searches the class C represented by
     771      * this {@code Class}, then the interfaces implemented by C and finally the
     772      * superclasses of C.
     773      *
     774      * @param name
     775      *            the name of the requested field.
     776      * @return the public field specified by {@code name}.
     777      * @throws NoSuchFieldException
     778      *             if the field can not be found.
     779      * @see #getDeclaredField(String)
     780      */
     781     public Field getField(String name) throws NoSuchFieldException {
     782         if (name == null) {
     783             throw new NullPointerException("name == null");
     784         }
     785         Field result = getPublicFieldRecursive(name);
     786         if (result == null) {
     787             throw new NoSuchFieldException(name);
     788         }
     789         return result;
     790     }
     791 
     792     private Field getPublicFieldRecursive(String name) {
     793         // search superclasses
     794         for (Class<?> c = this; c != null; c = c.getSuperclass()) {
     795             Field result = Class.getDeclaredField(c, name);
     796             if (result != null && (result.getModifiers() & Modifier.PUBLIC) != 0) {
     797                 return result;
     798             }
     799         }
     800 
     801         // search implemented interfaces
     802         for (Class<?> c = this; c != null; c = c.getSuperclass()) {
     803             for (Class<?> ifc : c.getInterfaces()) {
     804                 Field result = ifc.getPublicFieldRecursive(name);
     805                 if (result != null && (result.getModifiers() & Modifier.PUBLIC) != 0) {
     806                     return result;
     807                 }
     808             }
     809         }
     810 
     811         return null;
     812     }
     813 
     814     /**
     815      * Returns an array containing {@code Field} objects for all public fields
     816      * for the class C represented by this {@code Class}. Fields may be declared
     817      * in C, the interfaces it implements or in the superclasses of C. The
     818      * elements in the returned array are in no particular order.
     819      *
     820      * <p>If there are no public fields or if this class represents an array class,
     821      * a primitive type or {@code void} then an empty array is returned.
     822      *
     823      * @return an array with the public fields of the class represented by this
     824      *         {@code Class}.
     825      * @see #getDeclaredFields()
     826      */
     827     public Field[] getFields() {
     828         List<Field> fields = new ArrayList<Field>();
     829         getPublicFieldsRecursive(fields);
     830 
     831         /*
     832          * The result may include duplicates when clazz implements an interface
     833          * through multiple paths. Remove those duplicates.
     834          */
     835         CollectionUtils.removeDuplicates(fields, Field.ORDER_BY_NAME_AND_DECLARING_CLASS);
     836         return fields.toArray(new Field[fields.size()]);
     837     }
     838 
     839     /**
     840      * Populates {@code result} with public fields defined by this class, its
     841      * superclasses, and all implemented interfaces.
     842      */
     843     private void getPublicFieldsRecursive(List<Field> result) {
     844         // search superclasses
     845         for (Class<?> c = this; c != null; c = c.getSuperclass()) {
     846             for (Field field : Class.getDeclaredFields(c, true)) {
     847                 result.add(field);
     848             }
     849         }
     850 
     851         // search implemented interfaces
     852         for (Class<?> c = this; c != null; c = c.getSuperclass()) {
     853             for (Class<?> ifc : c.getInterfaces()) {
     854                 ifc.getPublicFieldsRecursive(result);
     855             }
     856         }
     857     }
     858 
     859     /**
     860      * Gets the {@link Type}s of the interfaces that this {@code Class} directly
     861      * implements. If the {@code Class} represents a primitive type or {@code
     862      * void} then an empty array is returned.
     863      *
     864      * @return an array of {@link Type} instances directly implemented by the
     865      *         class represented by this {@code class}.
     866      */
     867     public Type[] getGenericInterfaces() {
     868         GenericSignatureParser parser = new GenericSignatureParser(getClassLoader());
     869         parser.parseForClass(this, getSignatureAttribute());
     870         return Types.getClonedTypeArray(parser.interfaceTypes);
     871     }
     872 
     873     /**
     874      * Gets the {@code Type} that represents the superclass of this {@code
     875      * class}.
     876      *
     877      * @return an instance of {@code Type} representing the superclass.
     878      */
     879     public Type getGenericSuperclass() {
     880         GenericSignatureParser parser = new GenericSignatureParser(getClassLoader());
     881         parser.parseForClass(this, getSignatureAttribute());
     882         return Types.getType(parser.superclassType);
     883     }
     884 
     885     /**
     886      * Returns an array of {@code Class} objects that match the interfaces
     887      * specified in the {@code implements} declaration of the class represented
     888      * by this {@code Class}. The order of the elements in the array is
     889      * identical to the order in the original class declaration. If the class
     890      * does not implement any interfaces, an empty array is returned.
     891      *
     892      * @return an array with the interfaces of the class represented by this
     893      *         class.
     894      */
     895     public native Class<?>[] getInterfaces();
     896 
     897     /**
     898      * Returns a {@code Method} object which represents the public method with
     899      * the specified name and parameter types. This method first searches the
     900      * class C represented by this {@code Class}, then the superclasses of C and
     901      * finally the interfaces implemented by C and finally the superclasses of C
     902      * for a method with matching name.
     903      *
     904      * @param name
     905      *            the requested method's name.
     906      * @param parameterTypes
     907      *            the parameter types of the requested method.
     908      *            {@code (Class[]) null} is equivalent to the empty array.
     909      * @return the public field specified by {@code name}.
     910      * @throws NoSuchMethodException
     911      *             if the method can not be found.
     912      * @see #getDeclaredMethod(String, Class[])
     913      */
     914     public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException {
     915         Member member = getConstructorOrMethod(name, true, true, parameterTypes);
     916         if (member instanceof Constructor) {
     917             throw new NoSuchMethodException(name);
     918         }
     919         return (Method) member;
     920     }
     921 
     922     /**
     923      * Returns an array containing {@code Method} objects for all public methods
     924      * for the class C represented by this {@code Class}. Methods may be
     925      * declared in C, the interfaces it implements or in the superclasses of C.
     926      * The elements in the returned array are in no particular order.
     927      * <p>
     928      * If there are no public methods or if this {@code Class} represents a
     929      * primitive type or {@code void} then an empty array is returned.
     930      * </p>
     931      *
     932      * @return an array with the methods of the class represented by this
     933      *         {@code Class}.
     934      * @see #getDeclaredMethods()
     935      */
     936     public Method[] getMethods() {
     937         List<Method> methods = new ArrayList<Method>();
     938         getPublicMethodsRecursive(methods);
     939 
     940         /*
     941          * Remove methods defined by multiple types, preferring to keep methods
     942          * declared by derived types.
     943          */
     944         CollectionUtils.removeDuplicates(methods, Method.ORDER_BY_SIGNATURE);
     945         return methods.toArray(new Method[methods.size()]);
     946     }
     947 
     948     /**
     949      * Populates {@code result} with public methods defined by {@code clazz}, its
     950      * superclasses, and all implemented interfaces, including overridden methods.
     951      */
     952     private void getPublicMethodsRecursive(List<Method> result) {
     953         // search superclasses
     954         for (Class<?> c = this; c != null; c = c.getSuperclass()) {
     955             for (Method method : Class.getDeclaredMethods(c, true)) {
     956                 result.add(method);
     957             }
     958         }
     959 
     960         // search implemented interfaces
     961         for (Class<?> c = this; c != null; c = c.getSuperclass()) {
     962             for (Class<?> ifc : c.getInterfaces()) {
     963                 ifc.getPublicMethodsRecursive(result);
     964             }
     965         }
     966     }
     967 
     968     /**
     969      * Returns an integer that represents the modifiers of the class represented
     970      * by this {@code Class}. The returned value is a combination of bits
     971      * defined by constants in the {@link Modifier} class.
     972      *
     973      * @return the modifiers of the class represented by this {@code Class}.
     974      */
     975     public int getModifiers() {
     976         return getModifiers(this, false);
     977     }
     978 
     979     /*
     980      * Return the modifiers for the given class.
     981      *
     982      * @param clazz the class of interest
     983      * @ignoreInnerClassesAttrib determines whether we look for and use the
     984      *     flags from an "inner class" attribute
     985      */
     986     private static native int getModifiers(Class<?> clazz, boolean ignoreInnerClassesAttrib);
     987 
     988     /**
     989      * Returns the name of the class represented by this {@code Class}. For a
     990      * description of the format which is used, see the class definition of
     991      * {@link Class}.
     992      *
     993      * @return the name of the class represented by this {@code Class}.
     994      */
     995     public String getName() {
     996         String result = name;
     997         return (result == null) ? (name = getNameNative()) : result;
     998     }
     999 
    1000     private native String getNameNative();
    1001 
    1002     /**
    1003      * Returns the simple name of the class represented by this {@code Class} as
    1004      * defined in the source code. If there is no name (that is, the class is
    1005      * anonymous) then an empty string is returned. If the receiver is an array
    1006      * then the name of the underlying type with square braces appended (for
    1007      * example {@code "Integer[]"}) is returned.
    1008      *
    1009      * @return the simple name of the class represented by this {@code Class}.
    1010      */
    1011     public String getSimpleName() {
    1012         if (isArray()) {
    1013             return getComponentType().getSimpleName() + "[]";
    1014         }
    1015 
    1016         String name = getName();
    1017 
    1018         if (isAnonymousClass()) {
    1019             return "";
    1020         }
    1021 
    1022         if (isMemberClass() || isLocalClass()) {
    1023             return getInnerClassName();
    1024         }
    1025 
    1026         int dot = name.lastIndexOf('.');
    1027         if (dot != -1) {
    1028             return name.substring(dot + 1);
    1029         }
    1030 
    1031         return name;
    1032     }
    1033 
    1034     /*
    1035      * Returns the simple name of a member or local class, or null otherwise.
    1036      *
    1037      * @return The name.
    1038      */
    1039     private native String getInnerClassName();
    1040 
    1041     /**
    1042      * Returns null.
    1043      */
    1044     public ProtectionDomain getProtectionDomain() {
    1045         return null;
    1046     }
    1047 
    1048     /**
    1049      * Returns the URL of the resource specified by {@code resName}. The mapping
    1050      * between the resource name and the URL is managed by the class' class
    1051      * loader.
    1052      *
    1053      * @param resName
    1054      *            the name of the resource.
    1055      * @return the requested resource's {@code URL} object or {@code null} if
    1056      *         the resource can not be found.
    1057      * @see ClassLoader
    1058      */
    1059     public URL getResource(String resName) {
    1060         // Get absolute resource name, but without the leading slash
    1061         if (resName.startsWith("/")) {
    1062             resName = resName.substring(1);
    1063         } else {
    1064             String pkg = getName();
    1065             int dot = pkg.lastIndexOf('.');
    1066             if (dot != -1) {
    1067                 pkg = pkg.substring(0, dot).replace('.', '/');
    1068             } else {
    1069                 pkg = "";
    1070             }
    1071 
    1072             resName = pkg + "/" + resName;
    1073         }
    1074 
    1075         // Delegate to proper class loader
    1076         ClassLoader loader = getClassLoader();
    1077         if (loader != null) {
    1078             return loader.getResource(resName);
    1079         } else {
    1080             return ClassLoader.getSystemResource(resName);
    1081         }
    1082     }
    1083 
    1084     /**
    1085      * Returns a read-only stream for the contents of the resource specified by
    1086      * {@code resName}. The mapping between the resource name and the stream is
    1087      * managed by the class' class loader.
    1088      *
    1089      * @param resName
    1090      *            the name of the resource.
    1091      * @return a stream for the requested resource or {@code null} if no
    1092      *         resource with the specified name can be found.
    1093      * @see ClassLoader
    1094      */
    1095     public InputStream getResourceAsStream(String resName) {
    1096         // Get absolute resource name, but without the leading slash
    1097         if (resName.startsWith("/")) {
    1098             resName = resName.substring(1);
    1099         } else {
    1100             String pkg = getName();
    1101             int dot = pkg.lastIndexOf('.');
    1102             if (dot != -1) {
    1103                 pkg = pkg.substring(0, dot).replace('.', '/');
    1104             } else {
    1105                 pkg = "";
    1106             }
    1107 
    1108             resName = pkg + "/" + resName;
    1109         }
    1110 
    1111         // Delegate to proper class loader
    1112         ClassLoader loader = getClassLoader();
    1113         if (loader != null) {
    1114             return loader.getResourceAsStream(resName);
    1115         } else {
    1116             return ClassLoader.getSystemResourceAsStream(resName);
    1117         }
    1118     }
    1119 
    1120     /**
    1121      * Returns null. (On Android, a {@code ClassLoader} can load classes from multiple dex files.
    1122      * All classes from any given dex file will have the same signers, but different dex
    1123      * files may have different signers. This does not fit well with the original
    1124      * {@code ClassLoader}-based model of {@code getSigners}.)
    1125      *
    1126      * @return null.
    1127      */
    1128     public Object[] getSigners() {
    1129         // See http://code.google.com/p/android/issues/detail?id=1766.
    1130         return null;
    1131     }
    1132 
    1133     /**
    1134      * Returns the {@code Class} object which represents the superclass of the
    1135      * class represented by this {@code Class}. If this {@code Class} represents
    1136      * the {@code Object} class, a primitive type, an interface or void then the
    1137      * method returns {@code null}. If this {@code Class} represents an array
    1138      * class then the {@code Object} class is returned.
    1139      *
    1140      * @return the superclass of the class represented by this {@code Class}.
    1141      */
    1142     public native Class<? super T> getSuperclass();
    1143 
    1144     /**
    1145      * Returns an array containing {@code TypeVariable} objects for type
    1146      * variables declared by the generic class represented by this {@code
    1147      * Class}. Returns an empty array if the class is not generic.
    1148      *
    1149      * @return an array with the type variables of the class represented by this
    1150      *         class.
    1151      */
    1152     @SuppressWarnings("unchecked")
    1153     public synchronized TypeVariable<Class<T>>[] getTypeParameters() {
    1154         GenericSignatureParser parser = new GenericSignatureParser(getClassLoader());
    1155         parser.parseForClass(this, getSignatureAttribute());
    1156         return parser.formalTypeParameters.clone();
    1157     }
    1158 
    1159     /**
    1160      * Indicates whether this {@code Class} represents an annotation class.
    1161      *
    1162      * @return {@code true} if this {@code Class} represents an annotation
    1163      *         class; {@code false} otherwise.
    1164      */
    1165     public boolean isAnnotation() {
    1166         final int ACC_ANNOTATION = 0x2000;  // not public in reflect.Modifiers
    1167         int mod = getModifiers(this, true);
    1168         return (mod & ACC_ANNOTATION) != 0;
    1169     }
    1170 
    1171     @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
    1172         if (annotationType == null) {
    1173             throw new NullPointerException("annotationType == null");
    1174         }
    1175 
    1176         if (isDeclaredAnnotationPresent(annotationType)) {
    1177             return true;
    1178         }
    1179 
    1180         if (annotationType.isDeclaredAnnotationPresent(Inherited.class)) {
    1181             for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
    1182                 if (sup.isDeclaredAnnotationPresent(annotationType)) {
    1183                     return true;
    1184                 }
    1185             }
    1186         }
    1187 
    1188         return false;
    1189     }
    1190 
    1191     /**
    1192      * Indicates whether the class represented by this {@code Class} is
    1193      * anonymously declared.
    1194      *
    1195      * @return {@code true} if the class represented by this {@code Class} is
    1196      *         anonymous; {@code false} otherwise.
    1197      */
    1198     native public boolean isAnonymousClass();
    1199 
    1200     /**
    1201      * Indicates whether the class represented by this {@code Class} is an array
    1202      * class.
    1203      *
    1204      * @return {@code true} if the class represented by this {@code Class} is an
    1205      *         array class; {@code false} otherwise.
    1206      */
    1207     public boolean isArray() {
    1208         return getComponentType() != null;
    1209     }
    1210 
    1211     /**
    1212      * Indicates whether the specified class type can be converted to the class
    1213      * represented by this {@code Class}. Conversion may be done via an identity
    1214      * conversion or a widening reference conversion (if either the receiver or
    1215      * the argument represent primitive types, only the identity conversion
    1216      * applies).
    1217      *
    1218      * @param cls
    1219      *            the class to check.
    1220      * @return {@code true} if {@code cls} can be converted to the class
    1221      *         represented by this {@code Class}; {@code false} otherwise.
    1222      * @throws NullPointerException
    1223      *             if {@code cls} is {@code null}.
    1224      */
    1225     public native boolean isAssignableFrom(Class<?> cls);
    1226 
    1227     /**
    1228      * Indicates whether the class represented by this {@code Class} is an
    1229      * {@code enum}.
    1230      *
    1231      * @return {@code true} if the class represented by this {@code Class} is an
    1232      *         {@code enum}; {@code false} otherwise.
    1233      */
    1234     public boolean isEnum() {
    1235         return ((getModifiers() & 0x4000) != 0) && (getSuperclass() == Enum.class);
    1236     }
    1237 
    1238     /**
    1239      * Indicates whether the specified object can be cast to the class
    1240      * represented by this {@code Class}. This is the runtime version of the
    1241      * {@code instanceof} operator.
    1242      *
    1243      * @param object
    1244      *            the object to check.
    1245      * @return {@code true} if {@code object} can be cast to the type
    1246      *         represented by this {@code Class}; {@code false} if {@code
    1247      *         object} is {@code null} or cannot be cast.
    1248      */
    1249     public native boolean isInstance(Object object);
    1250 
    1251     /**
    1252      * Indicates whether this {@code Class} represents an interface.
    1253      *
    1254      * @return {@code true} if this {@code Class} represents an interface;
    1255      *         {@code false} otherwise.
    1256      */
    1257     public native boolean isInterface();
    1258 
    1259     /**
    1260      * Indicates whether the class represented by this {@code Class} is defined
    1261      * locally.
    1262      *
    1263      * @return {@code true} if the class represented by this {@code Class} is
    1264      *         defined locally; {@code false} otherwise.
    1265      */
    1266     public boolean isLocalClass() {
    1267         boolean enclosed = (getEnclosingMethod() != null ||
    1268                          getEnclosingConstructor() != null);
    1269         return enclosed && !isAnonymousClass();
    1270     }
    1271 
    1272     /**
    1273      * Indicates whether the class represented by this {@code Class} is a member
    1274      * class.
    1275      *
    1276      * @return {@code true} if the class represented by this {@code Class} is a
    1277      *         member class; {@code false} otherwise.
    1278      */
    1279     public boolean isMemberClass() {
    1280         return getDeclaringClass() != null;
    1281     }
    1282 
    1283     /**
    1284      * Indicates whether this {@code Class} represents a primitive type.
    1285      *
    1286      * @return {@code true} if this {@code Class} represents a primitive type;
    1287      *         {@code false} otherwise.
    1288      */
    1289     public native boolean isPrimitive();
    1290 
    1291     /**
    1292      * Indicates whether this {@code Class} represents a synthetic type.
    1293      *
    1294      * @return {@code true} if this {@code Class} represents a synthetic type;
    1295      *         {@code false} otherwise.
    1296      */
    1297     public boolean isSynthetic() {
    1298         final int ACC_SYNTHETIC = 0x1000;   // not public in reflect.Modifiers
    1299         int mod = getModifiers(this, true);
    1300         return (mod & ACC_SYNTHETIC) != 0;
    1301     }
    1302 
    1303     /**
    1304      * Returns a new instance of the class represented by this {@code Class},
    1305      * created by invoking the default (that is, zero-argument) constructor. If
    1306      * there is no such constructor, or if the creation fails (either because of
    1307      * a lack of available memory or because an exception is thrown by the
    1308      * constructor), an {@code InstantiationException} is thrown. If the default
    1309      * constructor exists but is not accessible from the context where this
    1310      * method is invoked, an {@code IllegalAccessException} is thrown.
    1311      *
    1312      * @return a new instance of the class represented by this {@code Class}.
    1313      * @throws IllegalAccessException
    1314      *             if the default constructor is not visible.
    1315      * @throws InstantiationException
    1316      *             if the instance can not be created.
    1317      */
    1318     public T newInstance() throws InstantiationException, IllegalAccessException {
    1319         return newInstanceImpl();
    1320     }
    1321 
    1322     private native T newInstanceImpl() throws IllegalAccessException, InstantiationException;
    1323 
    1324     @Override
    1325     public String toString() {
    1326         if (isPrimitive()) {
    1327             return getSimpleName();
    1328         } else {
    1329             return (isInterface() ? "interface " : "class ") + getName();
    1330         }
    1331     }
    1332 
    1333     /**
    1334      * Returns the {@code Package} of which the class represented by this
    1335      * {@code Class} is a member. Returns {@code null} if no {@code Package}
    1336      * object was created by the class loader of the class.
    1337      *
    1338      * @return Package the {@code Package} of which this {@code Class} is a
    1339      *         member or {@code null}.
    1340      */
    1341     public Package getPackage() {
    1342         // TODO This might be a hack, but the VM doesn't have the necessary info.
    1343         ClassLoader loader = getClassLoader();
    1344         if (loader != null) {
    1345             String name = getName();
    1346             int dot = name.lastIndexOf('.');
    1347             return (dot != -1 ? loader.getPackage(name.substring(0, dot)) : null);
    1348         }
    1349         return null;
    1350     }
    1351 
    1352     /**
    1353      * Returns the assertion status for the class represented by this {@code
    1354      * Class}. Assertion is enabled / disabled based on the class loader,
    1355      * package or class default at runtime.
    1356      *
    1357      * @return the assertion status for the class represented by this {@code
    1358      *         Class}.
    1359      */
    1360     public native boolean desiredAssertionStatus();
    1361 
    1362     /**
    1363      * Casts this {@code Class} to represent a subclass of the specified class.
    1364      * If successful, this {@code Class} is returned; otherwise a {@code
    1365      * ClassCastException} is thrown.
    1366      *
    1367      * @param clazz
    1368      *            the required type.
    1369      * @return this {@code Class} cast as a subclass of the given type.
    1370      * @throws ClassCastException
    1371      *             if this {@code Class} cannot be cast to the specified type.
    1372      */
    1373     @SuppressWarnings("unchecked")
    1374     public <U> Class<? extends U> asSubclass(Class<U> clazz) {
    1375         if (clazz.isAssignableFrom(this)) {
    1376             return (Class<? extends U>)this;
    1377         }
    1378         String actualClassName = this.getName();
    1379         String desiredClassName = clazz.getName();
    1380         throw new ClassCastException(actualClassName + " cannot be cast to " + desiredClassName);
    1381     }
    1382 
    1383     /**
    1384      * Casts the specified object to the type represented by this {@code Class}.
    1385      * If the object is {@code null} then the result is also {@code null}.
    1386      *
    1387      * @param obj
    1388      *            the object to cast.
    1389      * @return the object that has been cast.
    1390      * @throws ClassCastException
    1391      *             if the object cannot be cast to the specified type.
    1392      */
    1393     @SuppressWarnings("unchecked")
    1394     public T cast(Object obj) {
    1395         if (obj == null) {
    1396             return null;
    1397         } else if (this.isInstance(obj)) {
    1398             return (T)obj;
    1399         }
    1400         String actualClassName = obj.getClass().getName();
    1401         String desiredClassName = this.getName();
    1402         throw new ClassCastException(actualClassName + " cannot be cast to " + desiredClassName);
    1403     }
    1404 
    1405     /**
    1406      * Copies two arrays into one. Assumes that the destination array is large
    1407      * enough.
    1408      *
    1409      * @param result the destination array
    1410      * @param head the first source array
    1411      * @param tail the second source array
    1412      * @return the destination array, that is, result
    1413      */
    1414     private static <T extends Object> T[] arraycopy(T[] result, T[] head, T[] tail) {
    1415         System.arraycopy(head, 0, result, 0, head.length);
    1416         System.arraycopy(tail, 0, result, head.length, tail.length);
    1417         return result;
    1418     }
    1419 }
    View Code

    Constructor

      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 /*
     18  * Copyright (C) 2008 The Android Open Source Project
     19  *
     20  * Licensed under the Apache License, Version 2.0 (the "License");
     21  * you may not use this file except in compliance with the License.
     22  * You may obtain a copy of the License at
     23  *
     24  *      http://www.apache.org/licenses/LICENSE-2.0
     25  *
     26  * Unless required by applicable law or agreed to in writing, software
     27  * distributed under the License is distributed on an "AS IS" BASIS,
     28  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     29  * See the License for the specific language governing permissions and
     30  * limitations under the License.
     31  */
     32 
     33 package java.lang.reflect;
     34 
     35 import java.lang.annotation.Annotation;
     36 import libcore.util.EmptyArray;
     37 import org.apache.harmony.kernel.vm.StringUtils;
     38 import org.apache.harmony.luni.lang.reflect.GenericSignatureParser;
     39 import org.apache.harmony.luni.lang.reflect.ListOfTypes;
     40 import org.apache.harmony.luni.lang.reflect.Types;
     41 
     42 /**
     43  * This class represents a constructor. Information about the constructor can be
     44  * accessed, and the constructor can be invoked dynamically.
     45  *
     46  * @param <T> the class that declares this constructor
     47  */
     48 public final class Constructor<T> extends AccessibleObject implements GenericDeclaration,
     49         Member {
     50 
     51     Class<T> declaringClass;
     52 
     53     Class<?>[] parameterTypes;
     54 
     55     Class<?>[] exceptionTypes;
     56 
     57     ListOfTypes genericExceptionTypes;
     58     ListOfTypes genericParameterTypes;
     59     TypeVariable<Constructor<T>>[] formalTypeParameters;
     60     private volatile boolean genericTypesAreInitialized = false;
     61 
     62     private synchronized void initGenericTypes() {
     63         if (!genericTypesAreInitialized) {
     64             String signatureAttribute = getSignatureAttribute();
     65             GenericSignatureParser parser = new GenericSignatureParser(
     66                     declaringClass.getClassLoader());
     67             parser.parseForConstructor(this, signatureAttribute, exceptionTypes);
     68             formalTypeParameters = parser.formalTypeParameters;
     69             genericParameterTypes = parser.parameterTypes;
     70             genericExceptionTypes = parser.exceptionTypes;
     71             genericTypesAreInitialized = true;
     72         }
     73     }
     74 
     75     int slot;
     76 
     77     /**
     78      * Prevent this class from being instantiated.
     79      */
     80     private Constructor(){
     81         //do nothing
     82     }
     83 
     84     /**
     85      * Creates an instance of the class. Only called from native code, thus
     86      * private.
     87      *
     88      * @param declaringClass
     89      *            the class this constructor object belongs to
     90      * @param ptypes
     91      *            the parameter types of the constructor
     92      * @param extypes
     93      *            the exception types of the constructor
     94      * @param slot
     95      *            the slot of the constructor inside the VM class structure
     96      */
     97     private Constructor (Class<T> declaringClass, Class<?>[] ptypes, Class<?>[] extypes, int slot){
     98         this.declaringClass = declaringClass;
     99         this.parameterTypes = ptypes;
    100         this.exceptionTypes = extypes;          // may be null
    101         this.slot = slot;
    102     }
    103 
    104     @Override /*package*/ String getSignatureAttribute() {
    105         Object[] annotation = Method.getSignatureAnnotation(declaringClass, slot);
    106 
    107         if (annotation == null) {
    108             return null;
    109         }
    110 
    111         return StringUtils.combineStrings(annotation);
    112     }
    113 
    114     public TypeVariable<Constructor<T>>[] getTypeParameters() {
    115         initGenericTypes();
    116         return formalTypeParameters.clone();
    117     }
    118 
    119     /**
    120      * Returns the string representation of the constructor's declaration,
    121      * including the type parameters.
    122      *
    123      * @return the string representation of the constructor's declaration
    124      */
    125     public String toGenericString() {
    126         StringBuilder sb = new StringBuilder(80);
    127         initGenericTypes();
    128         // append modifiers if any
    129         int modifier = getModifiers();
    130         if (modifier != 0) {
    131             sb.append(Modifier.toString(modifier & ~Modifier.VARARGS)).append(' ');
    132         }
    133         // append type parameters
    134         if (formalTypeParameters != null && formalTypeParameters.length > 0) {
    135             sb.append('<');
    136             for (int i = 0; i < formalTypeParameters.length; i++) {
    137                 appendGenericType(sb, formalTypeParameters[i]);
    138                 if (i < formalTypeParameters.length - 1) {
    139                     sb.append(",");
    140                 }
    141             }
    142             sb.append("> ");
    143         }
    144         // append constructor name
    145         appendArrayType(sb, getDeclaringClass());
    146         // append parameters
    147         sb.append('(');
    148         appendArrayGenericType(sb,
    149                 Types.getClonedTypeArray(genericParameterTypes));
    150         sb.append(')');
    151         // append exceptions if any
    152         Type[] genericExceptionTypeArray =
    153                 Types.getClonedTypeArray(genericExceptionTypes);
    154         if (genericExceptionTypeArray.length > 0) {
    155             sb.append(" throws ");
    156             appendArrayGenericType(sb, genericExceptionTypeArray);
    157         }
    158         return sb.toString();
    159     }
    160 
    161     /**
    162      * Returns the generic parameter types as an array of {@code Type}
    163      * instances, in declaration order. If this constructor has no generic
    164      * parameters, an empty array is returned.
    165      *
    166      * @return the parameter types
    167      *
    168      * @throws GenericSignatureFormatError
    169      *             if the generic constructor signature is invalid
    170      * @throws TypeNotPresentException
    171      *             if any parameter type points to a missing type
    172      * @throws MalformedParameterizedTypeException
    173      *             if any parameter type points to a type that cannot be
    174      *             instantiated for some reason
    175      */
    176     public Type[] getGenericParameterTypes() {
    177         initGenericTypes();
    178         return Types.getClonedTypeArray(genericParameterTypes);
    179     }
    180 
    181     /**
    182      * Returns the exception types as an array of {@code Type} instances. If
    183      * this constructor has no declared exceptions, an empty array will be
    184      * returned.
    185      *
    186      * @return an array of generic exception types
    187      *
    188      * @throws GenericSignatureFormatError
    189      *             if the generic constructor signature is invalid
    190      * @throws TypeNotPresentException
    191      *             if any exception type points to a missing type
    192      * @throws MalformedParameterizedTypeException
    193      *             if any exception type points to a type that cannot be
    194      *             instantiated for some reason
    195      */
    196     public Type[] getGenericExceptionTypes() {
    197         initGenericTypes();
    198         return Types.getClonedTypeArray(genericExceptionTypes);
    199     }
    200 
    201     @Override
    202     public Annotation[] getDeclaredAnnotations() {
    203         return Method.getDeclaredAnnotations(declaringClass, slot);
    204     }
    205 
    206     @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
    207         if (annotationType == null) {
    208             throw new NullPointerException("annotationType == null");
    209         }
    210         return Method.getAnnotation(declaringClass, slot, annotationType);
    211     }
    212 
    213     @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
    214         if (annotationType == null) {
    215             throw new NullPointerException("annotationType == null");
    216         }
    217         return Method.isAnnotationPresent(declaringClass, slot, annotationType);
    218     }
    219 
    220     /**
    221      * Returns an array of arrays that represent the annotations of the formal
    222      * parameters of this constructor. If there are no parameters on this
    223      * constructor, then an empty array is returned. If there are no annotations
    224      * set, then an array of empty arrays is returned.
    225      *
    226      * @return an array of arrays of {@code Annotation} instances
    227      */
    228     public Annotation[][] getParameterAnnotations() {
    229         Annotation[][] parameterAnnotations
    230                 = Method.getParameterAnnotations(declaringClass, slot);
    231         if (parameterAnnotations.length == 0) {
    232             return Method.noAnnotations(parameterTypes.length);
    233         }
    234         return parameterAnnotations;
    235     }
    236 
    237     /**
    238      * Indicates whether or not this constructor takes a variable number of
    239      * arguments.
    240      *
    241      * @return {@code true} if a vararg is declare, otherwise
    242      *         {@code false}
    243      */
    244     public boolean isVarArgs() {
    245         int mods = Method.getMethodModifiers(declaringClass, slot);
    246         return (mods & Modifier.VARARGS) != 0;
    247     }
    248 
    249     /**
    250      * Indicates whether or not this constructor is synthetic (artificially
    251      * introduced by the compiler).
    252      *
    253      * @return {@code true} if this constructor is synthetic, {@code false}
    254      *         otherwise
    255      */
    256     public boolean isSynthetic() {
    257         int mods = Method.getMethodModifiers(declaringClass, slot);
    258         return (mods & Modifier.SYNTHETIC) != 0;
    259     }
    260 
    261     /**
    262      * Indicates whether or not the specified {@code object} is equal to this
    263      * constructor. To be equal, the specified object must be an instance
    264      * of {@code Constructor} with the same declaring class and parameter types
    265      * as this constructor.
    266      *
    267      * @param object
    268      *            the object to compare
    269      *
    270      * @return {@code true} if the specified object is equal to this
    271      *         constructor, {@code false} otherwise
    272      *
    273      * @see #hashCode
    274      */
    275     @Override
    276     public boolean equals(Object object) {
    277         return object instanceof Constructor && toString().equals(object.toString());
    278     }
    279 
    280     /**
    281      * Returns the class that declares this constructor.
    282      *
    283      * @return the declaring class
    284      */
    285     public Class<T> getDeclaringClass() {
    286         return declaringClass;
    287     }
    288 
    289     /**
    290      * Returns the exception types as an array of {@code Class} instances. If
    291      * this constructor has no declared exceptions, an empty array will be
    292      * returned.
    293      *
    294      * @return the declared exception classes
    295      */
    296     public Class<?>[] getExceptionTypes() {
    297         if (exceptionTypes == null) {
    298             return EmptyArray.CLASS;
    299         }
    300         return exceptionTypes.clone();
    301     }
    302 
    303     /**
    304      * Returns the modifiers for this constructor. The {@link Modifier} class
    305      * should be used to decode the result.
    306      *
    307      * @return the modifiers for this constructor
    308      *
    309      * @see Modifier
    310      */
    311     public int getModifiers() {
    312         return Method.getMethodModifiers(declaringClass, slot);
    313     }
    314 
    315     /**
    316      * Returns the name of this constructor.
    317      *
    318      * @return the name of this constructor
    319      */
    320     public String getName() {
    321         return declaringClass.getName();
    322     }
    323 
    324     /**
    325      * Returns an array of the {@code Class} objects associated with the
    326      * parameter types of this constructor. If the constructor was declared with
    327      * no parameters, an empty array will be returned.
    328      *
    329      * @return the parameter types
    330      */
    331     public Class<?>[] getParameterTypes() {
    332         return parameterTypes.clone();
    333     }
    334 
    335     /**
    336      * Returns the constructor's signature in non-printable form. This is called
    337      * (only) from IO native code and needed for deriving the serialVersionUID
    338      * of the class
    339      *
    340      * @return the constructor's signature
    341      */
    342     @SuppressWarnings("unused")
    343     private String getSignature() {
    344         StringBuilder result = new StringBuilder();
    345 
    346         result.append('(');
    347         for (int i = 0; i < parameterTypes.length; i++) {
    348             result.append(getSignature(parameterTypes[i]));
    349         }
    350         result.append(")V");
    351 
    352         return result.toString();
    353     }
    354 
    355     /**
    356      * Returns an integer hash code for this constructor. Constructors which are
    357      * equal return the same value for this method. The hash code for a
    358      * Constructor is the hash code of the name of the declaring class.
    359      *
    360      * @return the hash code
    361      *
    362      * @see #equals
    363      */
    364     @Override
    365     public int hashCode() {
    366         return declaringClass.getName().hashCode();
    367     }
    368 
    369     /**
    370      * Returns a new instance of the declaring class, initialized by dynamically
    371      * invoking the constructor represented by this {@code Constructor} object.
    372      * This reproduces the effect of {@code new declaringClass(arg1, arg2, ... ,
    373      * argN)} This method performs the following:
    374      * <ul>
    375      * <li>A new instance of the declaring class is created. If the declaring
    376      * class cannot be instantiated (i.e. abstract class, an interface, an array
    377      * type, or a primitive type) then an InstantiationException is thrown.</li>
    378      * <li>If this Constructor object is enforcing access control (see
    379      * {@link AccessibleObject}) and this constructor is not accessible from the
    380      * current context, an IllegalAccessException is thrown.</li>
    381      * <li>If the number of arguments passed and the number of parameters do not
    382      * match, an IllegalArgumentException is thrown.</li>
    383      * <li>For each argument passed:
    384      * <ul>
    385      * <li>If the corresponding parameter type is a primitive type, the argument
    386      * is unboxed. If the unboxing fails, an IllegalArgumentException is
    387      * thrown.</li>
    388      * <li>If the resulting argument cannot be converted to the parameter type
    389      * via a widening conversion, an IllegalArgumentException is thrown.</li>
    390      * </ul>
    391      * <li>The constructor represented by this {@code Constructor} object is
    392      * then invoked. If an exception is thrown during the invocation, it is
    393      * caught and wrapped in an InvocationTargetException. This exception is
    394      * then thrown. If the invocation completes normally, the newly initialized
    395      * object is returned.
    396      * </ul>
    397      *
    398      * @param args
    399      *            the arguments to the constructor
    400      *
    401      * @return the new, initialized, object
    402      *
    403      * @exception InstantiationException
    404      *                if the class cannot be instantiated
    405      * @exception IllegalAccessException
    406      *                if this constructor is not accessible
    407      * @exception IllegalArgumentException
    408      *                if an incorrect number of arguments are passed, or an
    409      *                argument could not be converted by a widening conversion
    410      * @exception InvocationTargetException
    411      *                if an exception was thrown by the invoked constructor
    412      *
    413      * @see AccessibleObject
    414      */
    415     public T newInstance(Object... args) throws InstantiationException, IllegalAccessException,
    416             IllegalArgumentException, InvocationTargetException {
    417         return constructNative (args, declaringClass, parameterTypes, slot, flag);
    418     }
    419 
    420     private native T constructNative(Object[] args, Class<T> declaringClass,
    421             Class<?>[] parameterTypes, int slot,
    422             boolean noAccessCheck) throws InstantiationException, IllegalAccessException,
    423             InvocationTargetException;
    424 
    425     /**
    426      * Returns a string containing a concise, human-readable description of this
    427      * constructor. The format of the string is:
    428      *
    429      * <ol>
    430      *   <li>modifiers (if any)
    431      *   <li>declaring class name
    432      *   <li>'('
    433      *   <li>parameter types, separated by ',' (if any)
    434      *   <li>')'
    435      *   <li>'throws' plus exception types, separated by ',' (if any)
    436      * </ol>
    437      *
    438      * For example:
    439      * {@code public String(byte[],String) throws UnsupportedEncodingException}
    440      *
    441      * @return a printable representation for this constructor
    442      */
    443     @Override
    444     public String toString() {
    445         StringBuilder result = new StringBuilder(Modifier.toString(getModifiers()));
    446 
    447         if (result.length() != 0)
    448             result.append(' ');
    449         result.append(declaringClass.getName());
    450         result.append("(");
    451         result.append(toString(parameterTypes));
    452         result.append(")");
    453         if (exceptionTypes != null && exceptionTypes.length != 0) {
    454             result.append(" throws ");
    455             result.append(toString(exceptionTypes));
    456         }
    457 
    458         return result.toString();
    459     }
    460 }
    View Code

    Field

      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 /*
     18  * Copyright (C) 2008 The Android Open Source Project
     19  *
     20  * Licensed under the Apache License, Version 2.0 (the "License");
     21  * you may not use this file except in compliance with the License.
     22  * You may obtain a copy of the License at
     23  *
     24  *      http://www.apache.org/licenses/LICENSE-2.0
     25  *
     26  * Unless required by applicable law or agreed to in writing, software
     27  * distributed under the License is distributed on an "AS IS" BASIS,
     28  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     29  * See the License for the specific language governing permissions and
     30  * limitations under the License.
     31  */
     32 
     33 package java.lang.reflect;
     34 
     35 import java.lang.annotation.Annotation;
     36 import java.util.Comparator;
     37 import org.apache.harmony.kernel.vm.StringUtils;
     38 import org.apache.harmony.luni.lang.reflect.GenericSignatureParser;
     39 import org.apache.harmony.luni.lang.reflect.Types;
     40 
     41 /**
     42  * This class represents a field. Information about the field can be accessed,
     43  * and the field's value can be accessed dynamically.
     44  */
     45 public final class Field extends AccessibleObject implements Member {
     46 
     47     /**
     48      * Orders fields by their name and declaring class.
     49      *
     50      * @hide
     51      */
     52     public static final Comparator<Field> ORDER_BY_NAME_AND_DECLARING_CLASS
     53             = new Comparator<Field>() {
     54         @Override public int compare(Field a, Field b) {
     55             int comparison = a.name.compareTo(b.name);
     56             if (comparison != 0) {
     57                 return comparison;
     58             }
     59 
     60             return a.getDeclaringClass().getName().compareTo(b.getDeclaringClass().getName());
     61         }
     62     };
     63 
     64     private Class<?> declaringClass;
     65 
     66     private Class<?> type;
     67 
     68     private Type genericType;
     69 
     70     private volatile boolean genericTypesAreInitialized = false;
     71 
     72     private String name;
     73 
     74     private int slot;
     75 
     76     private static final char TYPE_BOOLEAN = 'Z';
     77 
     78     private static final char TYPE_BYTE = 'B';
     79 
     80     private static final char TYPE_CHAR = 'C';
     81 
     82     private static final char TYPE_SHORT = 'S';
     83 
     84     private static final char TYPE_INTEGER = 'I';
     85 
     86     private static final char TYPE_FLOAT = 'F';
     87 
     88     private static final char TYPE_LONG = 'J';
     89 
     90     private static final char TYPE_DOUBLE = 'D';
     91 
     92     /**
     93      * Construct a clone of the given instance.
     94      *
     95      * @param orig non-null; the original instance to clone
     96      */
     97     /*package*/ Field(Field orig) {
     98         this(orig.declaringClass, orig.type, orig.name, orig.slot);
     99 
    100         // Copy the accessible flag.
    101         if (orig.flag) {
    102             this.flag = true;
    103         }
    104     }
    105 
    106     private Field(Class<?> declaringClass, Class<?> type, String name, int slot) {
    107         this.declaringClass = declaringClass;
    108         this.type = type;
    109         this.name = name;
    110         this.slot = slot;
    111     }
    112 
    113     private synchronized void initGenericType() {
    114         if (!genericTypesAreInitialized) {
    115             String signatureAttribute = getSignatureAttribute();
    116             GenericSignatureParser parser = new GenericSignatureParser(
    117                     declaringClass.getClassLoader());
    118             parser.parseForField(this.declaringClass, signatureAttribute);
    119             genericType = parser.fieldType;
    120             if (genericType == null) {
    121                 genericType = getType();
    122             }
    123             genericTypesAreInitialized = true;
    124         }
    125     }
    126 
    127     /** {@inheritDoc} */
    128     @Override
    129     /* package */String getSignatureAttribute() {
    130         Object[] annotation = getSignatureAnnotation(declaringClass, slot);
    131 
    132         if (annotation == null) {
    133             return null;
    134         }
    135 
    136         return StringUtils.combineStrings(annotation);
    137     }
    138 
    139     /**
    140      * Get the Signature annotation for this field. Returns null if not found.
    141      */
    142     native private Object[] getSignatureAnnotation(Class declaringClass, int slot);
    143 
    144     /**
    145      * Indicates whether or not this field is synthetic.
    146      *
    147      * @return {@code true} if this field is synthetic, {@code false} otherwise
    148      */
    149     public boolean isSynthetic() {
    150         int flags = getFieldModifiers(declaringClass, slot);
    151         return (flags & Modifier.SYNTHETIC) != 0;
    152     }
    153 
    154     /**
    155      * Returns the string representation of this field, including the field's
    156      * generic type.
    157      *
    158      * @return the string representation of this field
    159      */
    160     public String toGenericString() {
    161         StringBuilder sb = new StringBuilder(80);
    162         // append modifiers if any
    163         int modifier = getModifiers();
    164         if (modifier != 0) {
    165             sb.append(Modifier.toString(modifier)).append(' ');
    166         }
    167         // append generic type
    168         appendGenericType(sb, getGenericType());
    169         sb.append(' ');
    170         // append full field name
    171         sb.append(getDeclaringClass().getName()).append('.').append(getName());
    172         return sb.toString();
    173     }
    174 
    175     /**
    176      * Indicates whether or not this field is an enumeration constant.
    177      *
    178      * @return {@code true} if this field is an enumeration constant, {@code
    179      *         false} otherwise
    180      */
    181     public boolean isEnumConstant() {
    182         int flags = getFieldModifiers(declaringClass, slot);
    183         return (flags & Modifier.ENUM) != 0;
    184     }
    185 
    186     /**
    187      * Returns the generic type of this field.
    188      *
    189      * @return the generic type
    190      * @throws GenericSignatureFormatError
    191      *             if the generic field signature is invalid
    192      * @throws TypeNotPresentException
    193      *             if the generic type points to a missing type
    194      * @throws MalformedParameterizedTypeException
    195      *             if the generic type points to a type that cannot be
    196      *             instantiated for some reason
    197      */
    198     public Type getGenericType() {
    199         initGenericType();
    200         return Types.getType(genericType);
    201     }
    202 
    203     @Override public Annotation[] getDeclaredAnnotations() {
    204         return getDeclaredAnnotations(declaringClass, slot);
    205     }
    206     private static native Annotation[] getDeclaredAnnotations(Class declaringClass, int slot);
    207 
    208     @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
    209         if (annotationType == null) {
    210             throw new NullPointerException("annotationType == null");
    211         }
    212         return getAnnotation(declaringClass, slot, annotationType);
    213     }
    214     private static native <A extends Annotation> A getAnnotation(
    215             Class<?> declaringClass, int slot, Class<A> annotationType);
    216 
    217     @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
    218         if (annotationType == null) {
    219             throw new NullPointerException("annotationType == null");
    220         }
    221         return isAnnotationPresent(declaringClass, slot, annotationType);
    222     }
    223     private static native boolean isAnnotationPresent(
    224             Class<?> declaringClass, int slot, Class<? extends Annotation> annotationType);
    225 
    226     /**
    227      * Indicates whether or not the specified {@code object} is equal to this
    228      * field. To be equal, the specified object must be an instance of
    229      * {@code Field} with the same declaring class, type and name as this field.
    230      *
    231      * @param object
    232      *            the object to compare
    233      * @return {@code true} if the specified object is equal to this method,
    234      *         {@code false} otherwise
    235      * @see #hashCode
    236      */
    237     @Override
    238     public boolean equals(Object object) {
    239         return object instanceof Field && toString().equals(object.toString());
    240     }
    241 
    242     /**
    243      * Returns the value of the field in the specified object. This reproduces
    244      * the effect of {@code object.fieldName}
    245      *
    246      * <p>If the type of this field is a primitive type, the field value is
    247      * automatically boxed.
    248      *
    249      * <p>If this field is static, the object argument is ignored.
    250      * Otherwise, if the object is null, a NullPointerException is thrown. If
    251      * the object is not an instance of the declaring class of the method, an
    252      * IllegalArgumentException is thrown.
    253      *
    254      * <p>If this Field object is enforcing access control (see AccessibleObject)
    255      * and this field is not accessible from the current context, an
    256      * IllegalAccessException is thrown.
    257      *
    258      * @param object
    259      *            the object to access
    260      * @return the field value, possibly boxed
    261      * @throws NullPointerException
    262      *             if the object is {@code null} and the field is non-static
    263      * @throws IllegalArgumentException
    264      *             if the object is not compatible with the declaring class
    265      * @throws IllegalAccessException
    266      *             if this field is not accessible
    267      */
    268     public Object get(Object object) throws IllegalAccessException, IllegalArgumentException {
    269         return getField(object, declaringClass, type, slot, flag);
    270     }
    271 
    272     /**
    273      * Returns the value of the field in the specified object as a {@code
    274      * boolean}. This reproduces the effect of {@code object.fieldName}
    275      * <p>
    276      * If this field is static, the object argument is ignored.
    277      * Otherwise, if the object is {@code null}, a NullPointerException is
    278      * thrown. If the object is not an instance of the declaring class of the
    279      * method, an IllegalArgumentException is thrown.
    280      * <p>
    281      * If this Field object is enforcing access control (see AccessibleObject)
    282      * and this field is not accessible from the current context, an
    283      * IllegalAccessException is thrown.
    284      *
    285      * @param object
    286      *            the object to access
    287      * @return the field value
    288      * @throws NullPointerException
    289      *             if the object is {@code null} and the field is non-static
    290      * @throws IllegalArgumentException
    291      *             if the object is not compatible with the declaring class
    292      * @throws IllegalAccessException
    293      *             if this field is not accessible
    294      */
    295     public boolean getBoolean(Object object) throws IllegalAccessException,
    296             IllegalArgumentException {
    297         return getZField(object, declaringClass, type, slot, flag, TYPE_BOOLEAN);
    298     }
    299 
    300     /**
    301      * Returns the value of the field in the specified object as a {@code byte}.
    302      * This reproduces the effect of {@code object.fieldName}
    303      * <p>
    304      * If this field is static, the object argument is ignored.
    305      * Otherwise, if the object is {@code null}, a NullPointerException is
    306      * thrown. If the object is not an instance of the declaring class of the
    307      * method, an IllegalArgumentException is thrown.
    308      * <p>
    309      * If this Field object is enforcing access control (see AccessibleObject)
    310      * and this field is not accessible from the current context, an
    311      * IllegalAccessException is thrown.
    312      *
    313      * @param object
    314      *            the object to access
    315      * @return the field value
    316      * @throws NullPointerException
    317      *             if the object is {@code null} and the field is non-static
    318      * @throws IllegalArgumentException
    319      *             if the object is not compatible with the declaring class
    320      * @throws IllegalAccessException
    321      *             if this field is not accessible
    322      */
    323     public byte getByte(Object object) throws IllegalAccessException, IllegalArgumentException {
    324         return getBField(object, declaringClass, type, slot, flag, TYPE_BYTE);
    325     }
    326 
    327     /**
    328      * Returns the value of the field in the specified object as a {@code char}.
    329      * This reproduces the effect of {@code object.fieldName}
    330      * <p>
    331      * If this field is static, the object argument is ignored.
    332      * Otherwise, if the object is {@code null}, a NullPointerException is
    333      * thrown. If the object is not an instance of the declaring class of the
    334      * method, an IllegalArgumentException is thrown.
    335      * <p>
    336      * If this Field object is enforcing access control (see AccessibleObject)
    337      * and this field is not accessible from the current context, an
    338      * IllegalAccessException is thrown.
    339      *
    340      * @param object
    341      *            the object to access
    342      * @return the field value
    343      * @throws NullPointerException
    344      *             if the object is {@code null} and the field is non-static
    345      * @throws IllegalArgumentException
    346      *             if the object is not compatible with the declaring class
    347      * @throws IllegalAccessException
    348      *             if this field is not accessible
    349      */
    350     public char getChar(Object object) throws IllegalAccessException, IllegalArgumentException {
    351         return getCField(object, declaringClass, type, slot, flag, TYPE_CHAR);
    352     }
    353 
    354     /**
    355      * Returns the class that declares this field.
    356      *
    357      * @return the declaring class
    358      */
    359     public Class<?> getDeclaringClass() {
    360         return declaringClass;
    361     }
    362 
    363     /**
    364      * Returns the value of the field in the specified object as a {@code
    365      * double}. This reproduces the effect of {@code object.fieldName}
    366      * <p>
    367      * If this field is static, the object argument is ignored.
    368      * Otherwise, if the object is {@code null}, a NullPointerException is
    369      * thrown. If the object is not an instance of the declaring class of the
    370      * method, an IllegalArgumentException is thrown.
    371      * <p>
    372      * If this Field object is enforcing access control (see AccessibleObject)
    373      * and this field is not accessible from the current context, an
    374      * IllegalAccessException is thrown.
    375      *
    376      * @param object
    377      *            the object to access
    378      * @return the field value
    379      * @throws NullPointerException
    380      *             if the object is {@code null} and the field is non-static
    381      * @throws IllegalArgumentException
    382      *             if the object is not compatible with the declaring class
    383      * @throws IllegalAccessException
    384      *             if this field is not accessible
    385      */
    386     public double getDouble(Object object) throws IllegalAccessException, IllegalArgumentException {
    387         return getDField(object, declaringClass, type, slot, flag, TYPE_DOUBLE);
    388     }
    389 
    390     /**
    391      * Returns the value of the field in the specified object as a {@code float}
    392      * . This reproduces the effect of {@code object.fieldName}
    393      * <p>
    394      * If this field is static, the object argument is ignored.
    395      * Otherwise, if the object is {@code null}, a NullPointerException is
    396      * thrown. If the object is not an instance of the declaring class of the
    397      * method, an IllegalArgumentException is thrown.
    398      * <p>
    399      * If this Field object is enforcing access control (see AccessibleObject)
    400      * and this field is not accessible from the current context, an
    401      * IllegalAccessException is thrown.
    402      *
    403      * @param object
    404      *            the object to access
    405      * @return the field value
    406      * @throws NullPointerException
    407      *             if the object is {@code null} and the field is non-static
    408      * @throws IllegalArgumentException
    409      *             if the object is not compatible with the declaring class
    410      * @throws IllegalAccessException
    411      *             if this field is not accessible
    412      */
    413     public float getFloat(Object object) throws IllegalAccessException, IllegalArgumentException {
    414         return getFField(object, declaringClass, type, slot, flag, TYPE_FLOAT);
    415     }
    416 
    417     /**
    418      * Returns the value of the field in the specified object as an {@code int}.
    419      * This reproduces the effect of {@code object.fieldName}
    420      * <p>
    421      * If this field is static, the object argument is ignored.
    422      * Otherwise, if the object is {@code null}, a NullPointerException is
    423      * thrown. If the object is not an instance of the declaring class of the
    424      * method, an IllegalArgumentException is thrown.
    425      * <p>
    426      * If this Field object is enforcing access control (see AccessibleObject)
    427      * and this field is not accessible from the current context, an
    428      * IllegalAccessException is thrown.
    429      *
    430      * @param object
    431      *            the object to access
    432      * @return the field value
    433      * @throws NullPointerException
    434      *             if the object is {@code null} and the field is non-static
    435      * @throws IllegalArgumentException
    436      *             if the object is not compatible with the declaring class
    437      * @throws IllegalAccessException
    438      *             if this field is not accessible
    439      */
    440     public int getInt(Object object) throws IllegalAccessException, IllegalArgumentException {
    441         return getIField(object, declaringClass, type, slot, flag, TYPE_INTEGER);
    442     }
    443 
    444     /**
    445      * Returns the value of the field in the specified object as a {@code long}.
    446      * This reproduces the effect of {@code object.fieldName}
    447      * <p>
    448      * If this field is static, the object argument is ignored.
    449      * Otherwise, if the object is {@code null}, a NullPointerException is
    450      * thrown. If the object is not an instance of the declaring class of the
    451      * method, an IllegalArgumentException is thrown.
    452      * <p>
    453      * If this Field object is enforcing access control (see AccessibleObject)
    454      * and this field is not accessible from the current context, an
    455      * IllegalAccessException is thrown.
    456      *
    457      * @param object
    458      *            the object to access
    459      * @return the field value
    460      * @throws NullPointerException
    461      *             if the object is {@code null} and the field is non-static
    462      * @throws IllegalArgumentException
    463      *             if the object is not compatible with the declaring class
    464      * @throws IllegalAccessException
    465      *             if this field is not accessible
    466      */
    467     public long getLong(Object object) throws IllegalAccessException, IllegalArgumentException {
    468         return getJField(object, declaringClass, type, slot, flag, TYPE_LONG);
    469     }
    470 
    471     /**
    472      * Returns the modifiers for this field. The {@link Modifier} class should
    473      * be used to decode the result.
    474      *
    475      * @return the modifiers for this field
    476      * @see Modifier
    477      */
    478     public int getModifiers() {
    479         return getFieldModifiers(declaringClass, slot);
    480     }
    481 
    482     private native int getFieldModifiers(Class<?> declaringClass, int slot);
    483 
    484     /**
    485      * Returns the name of this field.
    486      *
    487      * @return the name of this field
    488      */
    489     public String getName() {
    490         return name;
    491     }
    492 
    493     /**
    494      * Returns the value of the field in the specified object as a {@code short}
    495      * . This reproduces the effect of {@code object.fieldName}
    496      * <p>
    497      * If this field is static, the object argument is ignored.
    498      * Otherwise, if the object is {@code null}, a NullPointerException is
    499      * thrown. If the object is not an instance of the declaring class of the
    500      * method, an IllegalArgumentException is thrown.
    501      * <p>
    502      * If this Field object is enforcing access control (see AccessibleObject)
    503      * and this field is not accessible from the current context, an
    504      * IllegalAccessException is thrown.
    505      *
    506      * @param object
    507      *            the object to access
    508      * @return the field value
    509      * @throws NullPointerException
    510      *             if the object is {@code null} and the field is non-static
    511      * @throws IllegalArgumentException
    512      *             if the object is not compatible with the declaring class
    513      * @throws IllegalAccessException
    514      *             if this field is not accessible
    515      */
    516     public short getShort(Object object) throws IllegalAccessException, IllegalArgumentException {
    517         return getSField(object, declaringClass, type, slot, flag, TYPE_SHORT);
    518     }
    519 
    520     /**
    521      * Returns the constructor's signature in non-printable form. This is called
    522      * (only) from IO native code and needed for deriving the serialVersionUID
    523      * of the class
    524      *
    525      * @return the constructor's signature.
    526      */
    527     @SuppressWarnings("unused")
    528     private String getSignature() {
    529         return getSignature(type);
    530     }
    531 
    532     /**
    533      * Return the {@link Class} associated with the type of this field.
    534      *
    535      * @return the type of this field
    536      */
    537     public Class<?> getType() {
    538         return type;
    539     }
    540 
    541     /**
    542      * Returns an integer hash code for this field. Objects which are equal
    543      * return the same value for this method.
    544      * <p>
    545      * The hash code for a Field is the exclusive-or combination of the hash
    546      * code of the field's name and the hash code of the name of its declaring
    547      * class.
    548      *
    549      * @return the hash code for this field
    550      * @see #equals
    551      */
    552     @Override
    553     public int hashCode() {
    554         return name.hashCode() ^ getDeclaringClass().getName().hashCode();
    555     }
    556 
    557     /**
    558      * Sets the value of the field in the specified object to the value. This
    559      * reproduces the effect of {@code object.fieldName = value}
    560      *
    561      * <p>If this field is static, the object argument is ignored.
    562      * Otherwise, if the object is {@code null}, a NullPointerException is
    563      * thrown. If the object is not an instance of the declaring class of the
    564      * method, an IllegalArgumentException is thrown.
    565      *
    566      * <p>If this Field object is enforcing access control (see AccessibleObject)
    567      * and this field is not accessible from the current context, an
    568      * IllegalAccessException is thrown.
    569      *
    570      * <p>If the field type is a primitive type, the value is automatically
    571      * unboxed. If the unboxing fails, an IllegalArgumentException is thrown. If
    572      * the value cannot be converted to the field type via a widening
    573      * conversion, an IllegalArgumentException is thrown.
    574      *
    575      * @param object
    576      *            the object to access
    577      * @param value
    578      *            the new value
    579      * @throws NullPointerException
    580      *             if the object is {@code null} and the field is non-static
    581      * @throws IllegalArgumentException
    582      *             if the object is not compatible with the declaring class
    583      * @throws IllegalAccessException
    584      *             if this field is not accessible
    585      */
    586     public void set(Object object, Object value) throws IllegalAccessException,
    587             IllegalArgumentException {
    588         setField(object, declaringClass, type, slot, flag, value);
    589     }
    590 
    591     /**
    592      * Sets the value of the field in the specified object to the {@code
    593      * boolean} value. This reproduces the effect of {@code object.fieldName =
    594      * value}
    595      * <p>
    596      * If this field is static, the object argument is ignored.
    597      * Otherwise, if the object is {@code null}, a NullPointerException is
    598      * thrown. If the object is not an instance of the declaring class of the
    599      * method, an IllegalArgumentException is thrown.
    600      * <p>
    601      * If this Field object is enforcing access control (see AccessibleObject)
    602      * and this field is not accessible from the current context, an
    603      * IllegalAccessException is thrown.
    604      * <p>
    605      * If the value cannot be converted to the field type via a widening
    606      * conversion, an IllegalArgumentException is thrown.
    607      *
    608      * @param object
    609      *            the object to access
    610      * @param value
    611      *            the new value
    612      * @throws NullPointerException
    613      *             if the object is {@code null} and the field is non-static
    614      * @throws IllegalArgumentException
    615      *             if the object is not compatible with the declaring class
    616      * @throws IllegalAccessException
    617      *             if this field is not accessible
    618      */
    619     public void setBoolean(Object object, boolean value) throws IllegalAccessException,
    620             IllegalArgumentException {
    621         setZField(object, declaringClass, type, slot, flag, TYPE_BOOLEAN, value);
    622     }
    623 
    624     /**
    625      * Sets the value of the field in the specified object to the {@code byte}
    626      * value. This reproduces the effect of {@code object.fieldName = value}
    627      * <p>
    628      * If this field is static, the object argument is ignored.
    629      * Otherwise, if the object is {@code null}, a NullPointerException is
    630      * thrown. If the object is not an instance of the declaring class of the
    631      * method, an IllegalArgumentException is thrown.
    632      * <p>
    633      * If this Field object is enforcing access control (see AccessibleObject)
    634      * and this field is not accessible from the current context, an
    635      * IllegalAccessException is thrown.
    636      * <p>
    637      * If the value cannot be converted to the field type via a widening
    638      * conversion, an IllegalArgumentException is thrown.
    639      *
    640      * @param object
    641      *            the object to access
    642      * @param value
    643      *            the new value
    644      * @throws NullPointerException
    645      *             if the object is {@code null} and the field is non-static
    646      * @throws IllegalArgumentException
    647      *             if the object is not compatible with the declaring class
    648      * @throws IllegalAccessException
    649      *             if this field is not accessible
    650      */
    651     public void setByte(Object object, byte value) throws IllegalAccessException,
    652             IllegalArgumentException {
    653         setBField(object, declaringClass, type, slot, flag, TYPE_BYTE, value);
    654     }
    655 
    656     /**
    657      * Sets the value of the field in the specified object to the {@code char}
    658      * value. This reproduces the effect of {@code object.fieldName = value}
    659      * <p>
    660      * If this field is static, the object argument is ignored.
    661      * Otherwise, if the object is {@code null}, a NullPointerException is
    662      * thrown. If the object is not an instance of the declaring class of the
    663      * method, an IllegalArgumentException is thrown.
    664      * <p>
    665      * If this Field object is enforcing access control (see AccessibleObject)
    666      * and this field is not accessible from the current context, an
    667      * IllegalAccessException is thrown.
    668      * <p>
    669      * If the value cannot be converted to the field type via a widening
    670      * conversion, an IllegalArgumentException is thrown.
    671      *
    672      * @param object
    673      *            the object to access
    674      * @param value
    675      *            the new value
    676      * @throws NullPointerException
    677      *             if the object is {@code null} and the field is non-static
    678      * @throws IllegalArgumentException
    679      *             if the object is not compatible with the declaring class
    680      * @throws IllegalAccessException
    681      *             if this field is not accessible
    682      */
    683     public void setChar(Object object, char value) throws IllegalAccessException,
    684             IllegalArgumentException {
    685         setCField(object, declaringClass, type, slot, flag, TYPE_CHAR, value);
    686     }
    687 
    688     /**
    689      * Sets the value of the field in the specified object to the {@code double}
    690      * value. This reproduces the effect of {@code object.fieldName = value}
    691      * <p>
    692      * If this field is static, the object argument is ignored.
    693      * Otherwise, if the object is {@code null}, a NullPointerException is
    694      * thrown. If the object is not an instance of the declaring class of the
    695      * method, an IllegalArgumentException is thrown.
    696      * <p>
    697      * If this Field object is enforcing access control (see AccessibleObject)
    698      * and this field is not accessible from the current context, an
    699      * IllegalAccessException is thrown.
    700      * <p>
    701      * If the value cannot be converted to the field type via a widening
    702      * conversion, an IllegalArgumentException is thrown.
    703      *
    704      * @param object
    705      *            the object to access
    706      * @param value
    707      *            the new value
    708      * @throws NullPointerException
    709      *             if the object is {@code null} and the field is non-static
    710      * @throws IllegalArgumentException
    711      *             if the object is not compatible with the declaring class
    712      * @throws IllegalAccessException
    713      *             if this field is not accessible
    714      */
    715     public void setDouble(Object object, double value) throws IllegalAccessException,
    716             IllegalArgumentException {
    717         setDField(object, declaringClass, type, slot, flag, TYPE_DOUBLE, value);
    718     }
    719 
    720     /**
    721      * Sets the value of the field in the specified object to the {@code float}
    722      * value. This reproduces the effect of {@code object.fieldName = value}
    723      * <p>
    724      * If this field is static, the object argument is ignored.
    725      * Otherwise, if the object is {@code null}, a NullPointerException is
    726      * thrown. If the object is not an instance of the declaring class of the
    727      * method, an IllegalArgumentException is thrown.
    728      * <p>
    729      * If this Field object is enforcing access control (see AccessibleObject)
    730      * and this field is not accessible from the current context, an
    731      * IllegalAccessException is thrown.
    732      * <p>
    733      * If the value cannot be converted to the field type via a widening
    734      * conversion, an IllegalArgumentException is thrown.
    735      *
    736      * @param object
    737      *            the object to access
    738      * @param value
    739      *            the new value
    740      * @throws NullPointerException
    741      *             if the object is {@code null} and the field is non-static
    742      * @throws IllegalArgumentException
    743      *             if the object is not compatible with the declaring class
    744      * @throws IllegalAccessException
    745      *             if this field is not accessible
    746      */
    747     public void setFloat(Object object, float value) throws IllegalAccessException,
    748             IllegalArgumentException {
    749         setFField(object, declaringClass, type, slot, flag, TYPE_FLOAT, value);
    750     }
    751 
    752     /**
    753      * Set the value of the field in the specified object to the {@code int}
    754      * value. This reproduces the effect of {@code object.fieldName = value}
    755      * <p>
    756      * If this field is static, the object argument is ignored.
    757      * Otherwise, if the object is {@code null}, a NullPointerException is
    758      * thrown. If the object is not an instance of the declaring class of the
    759      * method, an IllegalArgumentException is thrown.
    760      * <p>
    761      * If this Field object is enforcing access control (see AccessibleObject)
    762      * and this field is not accessible from the current context, an
    763      * IllegalAccessException is thrown.
    764      * <p>
    765      * If the value cannot be converted to the field type via a widening
    766      * conversion, an IllegalArgumentException is thrown.
    767      *
    768      * @param object
    769      *            the object to access
    770      * @param value
    771      *            the new value
    772      * @throws NullPointerException
    773      *             if the object is {@code null} and the field is non-static
    774      * @throws IllegalArgumentException
    775      *             if the object is not compatible with the declaring class
    776      * @throws IllegalAccessException
    777      *             if this field is not accessible
    778      */
    779     public void setInt(Object object, int value) throws IllegalAccessException,
    780             IllegalArgumentException {
    781         setIField(object, declaringClass, type, slot, flag, TYPE_INTEGER, value);
    782     }
    783 
    784     /**
    785      * Sets the value of the field in the specified object to the {@code long}
    786      * value. This reproduces the effect of {@code object.fieldName = value}
    787      * <p>
    788      * If this field is static, the object argument is ignored.
    789      * Otherwise, if the object is {@code null}, a NullPointerException is
    790      * thrown. If the object is not an instance of the declaring class of the
    791      * method, an IllegalArgumentException is thrown.
    792      * <p>
    793      * If this Field object is enforcing access control (see AccessibleObject)
    794      * and this field is not accessible from the current context, an
    795      * IllegalAccessException is thrown.
    796      * <p>
    797      * If the value cannot be converted to the field type via a widening
    798      * conversion, an IllegalArgumentException is thrown.
    799      *
    800      * @param object
    801      *            the object to access
    802      * @param value
    803      *            the new value
    804      * @throws NullPointerException
    805      *             if the object is {@code null} and the field is non-static
    806      * @throws IllegalArgumentException
    807      *             if the object is not compatible with the declaring class
    808      * @throws IllegalAccessException
    809      *             if this field is not accessible
    810      */
    811     public void setLong(Object object, long value) throws IllegalAccessException,
    812             IllegalArgumentException {
    813         setJField(object, declaringClass, type, slot, flag, TYPE_LONG, value);
    814     }
    815 
    816     /**
    817      * Sets the value of the field in the specified object to the {@code short}
    818      * value. This reproduces the effect of {@code object.fieldName = value}
    819      * <p>
    820      * If this field is static, the object argument is ignored.
    821      * Otherwise, if the object is {@code null}, a NullPointerException is
    822      * thrown. If the object is not an instance of the declaring class of the
    823      * method, an IllegalArgumentException is thrown.
    824      * <p>
    825      * If this Field object is enforcing access control (see AccessibleObject)
    826      * and this field is not accessible from the current context, an
    827      * IllegalAccessException is thrown.
    828      * <p>
    829      * If the value cannot be converted to the field type via a widening
    830      * conversion, an IllegalArgumentException is thrown.
    831      *
    832      * @param object
    833      *            the object to access
    834      * @param value
    835      *            the new value
    836      * @throws NullPointerException
    837      *             if the object is {@code null} and the field is non-static
    838      * @throws IllegalArgumentException
    839      *             if the object is not compatible with the declaring class
    840      * @throws IllegalAccessException
    841      *             if this field is not accessible
    842      */
    843     public void setShort(Object object, short value) throws IllegalAccessException,
    844             IllegalArgumentException {
    845         setSField(object, declaringClass, type, slot, flag, TYPE_SHORT, value);
    846     }
    847 
    848     /**
    849      * Returns a string containing a concise, human-readable description of this
    850      * field.
    851      * <p>
    852      * The format of the string is:
    853      * <ol>
    854      *   <li>modifiers (if any)
    855      *   <li>type
    856      *   <li>declaring class name
    857      *   <li>'.'
    858      *   <li>field name
    859      * </ol>
    860      * <p>
    861      * For example: {@code public static java.io.InputStream
    862      * java.lang.System.in}
    863      *
    864      * @return a printable representation for this field
    865      */
    866     @Override
    867     public String toString() {
    868         StringBuilder result = new StringBuilder(Modifier.toString(getModifiers()));
    869         if (result.length() != 0) {
    870             result.append(' ');
    871         }
    872         appendArrayType(result, type);
    873         result.append(' ');
    874         result.append(declaringClass.getName());
    875         result.append('.');
    876         result.append(name);
    877         return result.toString();
    878     }
    879 
    880     private native Object getField(Object o, Class<?> declaringClass, Class<?> type, int slot,
    881             boolean noAccessCheck) throws IllegalAccessException;
    882 
    883     private native double getDField(Object o, Class<?> declaringClass, Class<?> type, int slot,
    884             boolean noAccessCheck, char descriptor) throws IllegalAccessException;
    885 
    886     private native int getIField(Object o, Class<?> declaringClass, Class<?> type, int slot,
    887             boolean noAccessCheck, char descriptor) throws IllegalAccessException;
    888 
    889     private native long getJField(Object o, Class<?> declaringClass, Class<?> type, int slot,
    890             boolean noAccessCheck, char descriptor) throws IllegalAccessException;
    891 
    892     private native boolean getZField(Object o, Class<?> declaringClass, Class<?> type, int slot,
    893             boolean noAccessCheck, char descriptor) throws IllegalAccessException;
    894 
    895     private native float getFField(Object o, Class<?> declaringClass, Class<?> type, int slot,
    896             boolean noAccessCheck, char descriptor) throws IllegalAccessException;
    897 
    898     private native char getCField(Object o, Class<?> declaringClass, Class<?> type, int slot,
    899             boolean noAccessCheck, char descriptor) throws IllegalAccessException;
    900 
    901     private native short getSField(Object o, Class<?> declaringClass, Class<?> type, int slot,
    902             boolean noAccessCheck, char descriptor) throws IllegalAccessException;
    903 
    904     private native byte getBField(Object o, Class<?> declaringClass, Class<?> type, int slot,
    905             boolean noAccessCheck, char descriptor) throws IllegalAccessException;
    906 
    907     private native void setField(Object o, Class<?> declaringClass, Class<?> type, int slot,
    908             boolean noAccessCheck, Object value) throws IllegalAccessException;
    909 
    910     private native void setDField(Object o, Class<?> declaringClass, Class<?> type, int slot,
    911             boolean noAccessCheck, char descriptor, double v) throws IllegalAccessException;
    912 
    913     private native void setIField(Object o, Class<?> declaringClass, Class<?> type, int slot,
    914             boolean noAccessCheck, char descriptor, int i) throws IllegalAccessException;
    915 
    916     private native void setJField(Object o, Class<?> declaringClass, Class<?> type, int slot,
    917             boolean noAccessCheck, char descriptor, long j) throws IllegalAccessException;
    918 
    919     private native void setZField(Object o, Class<?> declaringClass, Class<?> type, int slot,
    920             boolean noAccessCheck, char descriptor, boolean z) throws IllegalAccessException;
    921 
    922     private native void setFField(Object o, Class<?> declaringClass, Class<?> type, int slot,
    923             boolean noAccessCheck, char descriptor, float f) throws IllegalAccessException;
    924 
    925     private native void setCField(Object o, Class<?> declaringClass, Class<?> type, int slot,
    926             boolean noAccessCheck, char descriptor, char c) throws IllegalAccessException;
    927 
    928     private native void setSField(Object o, Class<?> declaringClass, Class<?> type, int slot,
    929             boolean noAccessCheck, char descriptor, short s) throws IllegalAccessException;
    930 
    931     private native void setBField(Object o, Class<?> declaringClass, Class<?> type, int slot,
    932             boolean noAccessCheck, char descriptor, byte b) throws IllegalAccessException;
    933 
    934 }
    View Code

    Member

     1 /*
     2  *  Licensed to the Apache Software Foundation (ASF) under one or more
     3  *  contributor license agreements.  See the NOTICE file distributed with
     4  *  this work for additional information regarding copyright ownership.
     5  *  The ASF licenses this file to You under the Apache License, Version 2.0
     6  *  (the "License"); you may not use this file except in compliance with
     7  *  the License.  You may obtain a copy of the License at
     8  *
     9  *     http://www.apache.org/licenses/LICENSE-2.0
    10  *
    11  *  Unless required by applicable law or agreed to in writing, software
    12  *  distributed under the License is distributed on an "AS IS" BASIS,
    13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  *  See the License for the specific language governing permissions and
    15  *  limitations under the License.
    16  */
    17 
    18 package java.lang.reflect;
    19 
    20 /**
    21  * Common interface providing access to reflective information on class members.
    22  *
    23  * @see Field
    24  * @see Constructor
    25  * @see Method
    26  */
    27 public interface Member {
    28 
    29     /**
    30      * Designates all public members of a class or interface (including
    31      * inherited members).
    32      */
    33     public static final int PUBLIC = 0;
    34 
    35     /**
    36      * Designates all declared members of a class or interface (without
    37      * inherited members).
    38      */
    39     public static final int DECLARED = 1;
    40 
    41     /**
    42      * Returns the class that declares this member.
    43      *
    44      * @return the declaring class
    45      */
    46     @SuppressWarnings("unchecked")
    47     Class<?> getDeclaringClass();
    48 
    49     /**
    50      * Returns the modifiers for this member. The {@link Modifier} class should
    51      * be used to decode the result.
    52      *
    53      * @return the modifiers for this member
    54      *
    55      * @see Modifier
    56      */
    57     int getModifiers();
    58 
    59     /**
    60      * Returns the name of this member.
    61      *
    62      * @return the name of this member
    63      */
    64     String getName();
    65 
    66     /**
    67      * Indicates whether or not this member is synthetic (artificially
    68      * introduced by the compiler).
    69      *
    70      * @return {@code true} if this member is synthetic, {@code false} otherwise
    71      */
    72     boolean isSynthetic();
    73 }
    View Code

    Method

      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 /*
     18  * Copyright (C) 2008 The Android Open Source Project
     19  *
     20  * Licensed under the Apache License, Version 2.0 (the "License");
     21  * you may not use this file except in compliance with the License.
     22  * You may obtain a copy of the License at
     23  *
     24  *      http://www.apache.org/licenses/LICENSE-2.0
     25  *
     26  * Unless required by applicable law or agreed to in writing, software
     27  * distributed under the License is distributed on an "AS IS" BASIS,
     28  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     29  * See the License for the specific language governing permissions and
     30  * limitations under the License.
     31  */
     32 
     33 package java.lang.reflect;
     34 
     35 import java.lang.annotation.Annotation;
     36 import java.util.Comparator;
     37 import libcore.util.EmptyArray;
     38 import org.apache.harmony.kernel.vm.StringUtils;
     39 import org.apache.harmony.luni.lang.reflect.GenericSignatureParser;
     40 import org.apache.harmony.luni.lang.reflect.ListOfTypes;
     41 import org.apache.harmony.luni.lang.reflect.Types;
     42 
     43 /**
     44  * This class represents a method. Information about the method can be accessed,
     45  * and the method can be invoked dynamically.
     46  */
     47 public final class Method extends AccessibleObject implements GenericDeclaration, Member {
     48 
     49     /**
     50      * Orders methods by their name, parameters and return type.
     51      *
     52      * @hide
     53      */
     54     public static final Comparator<Method> ORDER_BY_SIGNATURE = new Comparator<Method>() {
     55         public int compare(Method a, Method b) {
     56             int comparison = a.name.compareTo(b.name);
     57             if (comparison != 0) {
     58                 return comparison;
     59             }
     60 
     61             Class<?>[] aParameters = a.parameterTypes;
     62             Class<?>[] bParameters = b.parameterTypes;
     63             int length = Math.min(aParameters.length, bParameters.length);
     64             for (int i = 0; i < length; i++) {
     65                 comparison = aParameters[i].getName().compareTo(bParameters[i].getName());
     66                 if (comparison != 0) {
     67                     return comparison;
     68                 }
     69             }
     70 
     71             if (aParameters.length != bParameters.length) {
     72                 return aParameters.length - bParameters.length;
     73             }
     74 
     75             // this is necessary for methods that have covariant return types.
     76             return a.getReturnType().getName().compareTo(b.getReturnType().getName());
     77         }
     78     };
     79 
     80     private int slot;
     81 
     82     private Class<?> declaringClass;
     83 
     84     private String name;
     85 
     86     private Class<?>[] parameterTypes;
     87 
     88     private Class<?>[] exceptionTypes;
     89 
     90     private Class<?> returnType;
     91 
     92     private ListOfTypes genericExceptionTypes;
     93     private ListOfTypes genericParameterTypes;
     94     private Type genericReturnType;
     95     private TypeVariable<Method>[] formalTypeParameters;
     96     private volatile boolean genericTypesAreInitialized = false;
     97 
     98     private synchronized void initGenericTypes() {
     99         if (!genericTypesAreInitialized) {
    100             String signatureAttribute = getSignatureAttribute();
    101             GenericSignatureParser parser = new GenericSignatureParser(
    102                     declaringClass.getClassLoader());
    103             parser.parseForMethod(this, signatureAttribute, exceptionTypes);
    104             formalTypeParameters = parser.formalTypeParameters;
    105             genericParameterTypes = parser.parameterTypes;
    106             genericExceptionTypes = parser.exceptionTypes;
    107             genericReturnType = parser.returnType;
    108             genericTypesAreInitialized = true;
    109         }
    110     }
    111 
    112     /**
    113      * Construct a clone of the given instance.
    114      *
    115      * @param orig non-null; the original instance to clone
    116      */
    117     /*package*/ Method(Method orig) {
    118         this(orig.declaringClass, orig.parameterTypes, orig.exceptionTypes,
    119                 orig.returnType, orig.name, orig.slot);
    120 
    121         // Copy the accessible flag.
    122         if (orig.flag) {
    123             this.flag = true;
    124         }
    125     }
    126 
    127     private Method(Class<?> declaring, Class<?>[] paramTypes, Class<?>[] exceptTypes, Class<?> returnType, String name, int slot)
    128     {
    129         this.declaringClass = declaring;
    130         this.name = name;
    131         this.slot = slot;
    132         this.parameterTypes = paramTypes;
    133         this.exceptionTypes = exceptTypes;      // may be null
    134         this.returnType = returnType;
    135     }
    136 
    137     public TypeVariable<Method>[] getTypeParameters() {
    138         initGenericTypes();
    139         return formalTypeParameters.clone();
    140     }
    141 
    142     /** {@inheritDoc} */
    143     @Override /*package*/ String getSignatureAttribute() {
    144         Object[] annotation = getSignatureAnnotation(declaringClass, slot);
    145 
    146         if (annotation == null) {
    147             return null;
    148         }
    149 
    150         return StringUtils.combineStrings(annotation);
    151     }
    152 
    153     /**
    154      * Returns the Signature annotation for this method. Returns {@code null} if
    155      * not found.
    156      */
    157     static native Object[] getSignatureAnnotation(Class declaringClass, int slot);
    158 
    159     /**
    160      * Returns the string representation of the method's declaration, including
    161      * the type parameters.
    162      *
    163      * @return the string representation of this method
    164      */
    165     public String toGenericString() {
    166         StringBuilder sb = new StringBuilder(80);
    167 
    168         initGenericTypes();
    169 
    170         // append modifiers if any
    171         int modifier = getModifiers();
    172         if (modifier != 0) {
    173             sb.append(Modifier.toString(modifier & ~(Modifier.BRIDGE +
    174                     Modifier.VARARGS))).append(' ');
    175         }
    176         // append type parameters
    177         if (formalTypeParameters != null && formalTypeParameters.length > 0) {
    178             sb.append('<');
    179             for (int i = 0; i < formalTypeParameters.length; i++) {
    180                 appendGenericType(sb, formalTypeParameters[i]);
    181                 if (i < formalTypeParameters.length - 1) {
    182                     sb.append(",");
    183                 }
    184             }
    185             sb.append("> ");
    186         }
    187         // append return type
    188         appendGenericType(sb, Types.getType(genericReturnType));
    189         sb.append(' ');
    190         // append method name
    191         appendArrayType(sb, getDeclaringClass());
    192         sb.append(".").append(getName());
    193         // append parameters
    194         sb.append('(');
    195         appendArrayGenericType(sb,
    196                 Types.getClonedTypeArray(genericParameterTypes));
    197         sb.append(')');
    198         // append exceptions if any
    199         Type[] genericExceptionTypeArray = Types.getClonedTypeArray(
    200                 genericExceptionTypes);
    201         if (genericExceptionTypeArray.length > 0) {
    202             sb.append(" throws ");
    203             appendArrayGenericType(sb, genericExceptionTypeArray);
    204         }
    205         return sb.toString();
    206     }
    207 
    208     /**
    209      * Returns the parameter types as an array of {@code Type} instances, in
    210      * declaration order. If this method has no parameters, an empty array is
    211      * returned.
    212      *
    213      * @return the parameter types
    214      *
    215      * @throws GenericSignatureFormatError
    216      *             if the generic method signature is invalid
    217      * @throws TypeNotPresentException
    218      *             if any parameter type points to a missing type
    219      * @throws MalformedParameterizedTypeException
    220      *             if any parameter type points to a type that cannot be
    221      *             instantiated for some reason
    222      */
    223     public Type[] getGenericParameterTypes() {
    224         initGenericTypes();
    225         return Types.getClonedTypeArray(genericParameterTypes);
    226     }
    227 
    228     /**
    229      * Returns the exception types as an array of {@code Type} instances. If
    230      * this method has no declared exceptions, an empty array will be returned.
    231      *
    232      * @return an array of generic exception types
    233      *
    234      * @throws GenericSignatureFormatError
    235      *             if the generic method signature is invalid
    236      * @throws TypeNotPresentException
    237      *             if any exception type points to a missing type
    238      * @throws MalformedParameterizedTypeException
    239      *             if any exception type points to a type that cannot be
    240      *             instantiated for some reason
    241      */
    242     public Type[] getGenericExceptionTypes() {
    243         initGenericTypes();
    244         return Types.getClonedTypeArray(genericExceptionTypes);
    245     }
    246 
    247     /**
    248      * Returns the return type of this method as a {@code Type} instance.
    249      *
    250      * @return the return type of this method
    251      *
    252      * @throws GenericSignatureFormatError
    253      *             if the generic method signature is invalid
    254      * @throws TypeNotPresentException
    255      *             if the return type points to a missing type
    256      * @throws MalformedParameterizedTypeException
    257      *             if the return type points to a type that cannot be
    258      *             instantiated for some reason
    259      */
    260     public Type getGenericReturnType() {
    261         initGenericTypes();
    262         return Types.getType(genericReturnType);
    263     }
    264 
    265     @Override
    266     public Annotation[] getDeclaredAnnotations() {
    267         return getDeclaredAnnotations(declaringClass, slot);
    268     }
    269     static native Annotation[] getDeclaredAnnotations(Class<?> declaringClass, int slot);
    270 
    271     @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
    272         if (annotationType == null) {
    273             throw new NullPointerException("annotationType == null");
    274         }
    275         return getAnnotation(declaringClass, slot, annotationType);
    276     }
    277     static native <A extends Annotation> A getAnnotation(
    278             Class<?> declaringClass, int slot, Class<A> annotationType);
    279 
    280     @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
    281         if (annotationType == null) {
    282             throw new NullPointerException("annotationType == null");
    283         }
    284         return isAnnotationPresent(declaringClass, slot, annotationType);
    285     }
    286     static native boolean isAnnotationPresent(
    287             Class<?> declaringClass, int slot, Class<? extends Annotation> annotationType);
    288 
    289     private static final Annotation[] NO_ANNOTATIONS = new Annotation[0];
    290 
    291     /**
    292      * Creates an array of empty Annotation arrays.
    293      */
    294     /*package*/ static Annotation[][] noAnnotations(int size) {
    295         Annotation[][] annotations = new Annotation[size][];
    296         for (int i = 0; i < size; i++) {
    297             annotations[i] = NO_ANNOTATIONS;
    298         }
    299         return annotations;
    300     }
    301 
    302     /**
    303      * Returns an array of arrays that represent the annotations of the formal
    304      * parameters of this method. If there are no parameters on this method,
    305      * then an empty array is returned. If there are no annotations set, then
    306      * and array of empty arrays is returned.
    307      *
    308      * @return an array of arrays of {@code Annotation} instances
    309      */
    310     public Annotation[][] getParameterAnnotations() {
    311         Annotation[][] parameterAnnotations
    312                 = getParameterAnnotations(declaringClass, slot);
    313         if (parameterAnnotations.length == 0) {
    314             return noAnnotations(parameterTypes.length);
    315         }
    316         return parameterAnnotations;
    317     }
    318 
    319     static native Annotation[][] getParameterAnnotations(Class declaringClass, int slot);
    320 
    321     /**
    322      * Indicates whether or not this method takes a variable number argument.
    323      *
    324      * @return {@code true} if a vararg is declared, {@code false} otherwise
    325      */
    326     public boolean isVarArgs() {
    327         int modifiers = getMethodModifiers(declaringClass, slot);
    328         return (modifiers & Modifier.VARARGS) != 0;
    329     }
    330 
    331     /**
    332      * Indicates whether or not this method is a bridge.
    333      *
    334      * @return {@code true} if this method is a bridge, {@code false} otherwise
    335      */
    336     public boolean isBridge() {
    337         int modifiers = getMethodModifiers(declaringClass, slot);
    338         return (modifiers & Modifier.BRIDGE) != 0;
    339     }
    340 
    341     /**
    342      * Indicates whether or not this method is synthetic.
    343      *
    344      * @return {@code true} if this method is synthetic, {@code false} otherwise
    345      */
    346     public boolean isSynthetic() {
    347         int modifiers = getMethodModifiers(declaringClass, slot);
    348         return (modifiers & Modifier.SYNTHETIC) != 0;
    349     }
    350 
    351     /**
    352      * Returns the default value for the annotation member represented by this
    353      * method.
    354      *
    355      * @return the default value, or {@code null} if none
    356      *
    357      * @throws TypeNotPresentException
    358      *             if this annotation member is of type {@code Class} and no
    359      *             definition can be found
    360      */
    361     public Object getDefaultValue() {
    362         return getDefaultValue(declaringClass, slot);
    363     }
    364     native private Object getDefaultValue(Class declaringClass, int slot);
    365 
    366     /**
    367      * Indicates whether or not the specified {@code object} is equal to this
    368      * method. To be equal, the specified object must be an instance
    369      * of {@code Method} with the same declaring class and parameter types
    370      * as this method.
    371      *
    372      * @param object
    373      *            the object to compare
    374      *
    375      * @return {@code true} if the specified object is equal to this
    376      *         method, {@code false} otherwise
    377      *
    378      * @see #hashCode
    379      */
    380     @Override
    381     public boolean equals(Object object) {
    382         return object instanceof Method && toString().equals(object.toString());
    383     }
    384 
    385     /**
    386      * Returns the class that declares this method.
    387      *
    388      * @return the declaring class
    389      */
    390     public Class<?> getDeclaringClass() {
    391         return declaringClass;
    392     }
    393 
    394     /**
    395      * Returns the exception types as an array of {@code Class} instances. If
    396      * this method has no declared exceptions, an empty array is returned.
    397      *
    398      * @return the declared exception classes
    399      */
    400     public Class<?>[] getExceptionTypes() {
    401         if (exceptionTypes == null) {
    402             return EmptyArray.CLASS;
    403         }
    404         return exceptionTypes.clone();
    405     }
    406 
    407     /**
    408      * Returns the modifiers for this method. The {@link Modifier} class should
    409      * be used to decode the result.
    410      *
    411      * @return the modifiers for this method
    412      *
    413      * @see Modifier
    414      */
    415     public int getModifiers() {
    416         return getMethodModifiers(declaringClass, slot);
    417     }
    418 
    419     static native int getMethodModifiers(Class<?> declaringClass, int slot);
    420 
    421     /**
    422      * Returns the name of the method represented by this {@code Method}
    423      * instance.
    424      *
    425      * @return the name of this method
    426      */
    427     public String getName() {
    428         return name;
    429     }
    430 
    431     /**
    432      * Returns an array of {@code Class} objects associated with the parameter
    433      * types of this method. If the method was declared with no parameters, an
    434      * empty array will be returned.
    435      *
    436      * @return the parameter types
    437      */
    438     public Class<?>[] getParameterTypes() {
    439         return parameterTypes.clone();
    440     }
    441 
    442     /**
    443      * Returns the {@code Class} associated with the return type of this
    444      * method.
    445      *
    446      * @return the return type
    447      */
    448     public Class<?> getReturnType() {
    449         return returnType;
    450     }
    451 
    452     /**
    453      * Returns an integer hash code for this method. Objects which are equal
    454      * return the same value for this method. The hash code for this Method is
    455      * the hash code of the name of this method.
    456      *
    457      * @return hash code for this method
    458      *
    459      * @see #equals
    460      */
    461     @Override
    462     public int hashCode() {
    463         return name.hashCode();
    464     }
    465 
    466     /**
    467      * Returns the result of dynamically invoking this method. Equivalent to
    468      * {@code receiver.methodName(arg1, arg2, ... , argN)}.
    469      *
    470      * <p>If the method is static, the receiver argument is ignored (and may be null).
    471      *
    472      * <p>If the method takes no arguments, you can pass {@code (Object[]) null} instead of
    473      * allocating an empty array.
    474      *
    475      * <p>If you're calling a varargs method, you need to pass an {@code Object[]} for the
    476      * varargs parameter: that conversion is usually done in {@code javac}, not the VM, and
    477      * the reflection machinery does not do this for you. (It couldn't, because it would be
    478      * ambiguous.)
    479      *
    480      * <p>Reflective method invocation follows the usual process for method lookup.
    481      *
    482      * <p>If an exception is thrown during the invocation it is caught and
    483      * wrapped in an InvocationTargetException. This exception is then thrown.
    484      *
    485      * <p>If the invocation completes normally, the return value itself is
    486      * returned. If the method is declared to return a primitive type, the
    487      * return value is boxed. If the return type is void, null is returned.
    488      *
    489      * @param receiver
    490      *            the object on which to call this method (or null for static methods)
    491      * @param args
    492      *            the arguments to the method
    493      * @return the result
    494      *
    495      * @throws NullPointerException
    496      *             if {@code receiver == null} for a non-static method
    497      * @throws IllegalAccessException
    498      *             if this method is not accessible (see {@link AccessibleObject})
    499      * @throws IllegalArgumentException
    500      *             if the number of arguments doesn't match the number of parameters, the receiver
    501      *             is incompatible with the declaring class, or an argument could not be unboxed
    502      *             or converted by a widening conversion to the corresponding parameter type
    503      * @throws InvocationTargetException
    504      *             if an exception was thrown by the invoked method
    505      */
    506     public Object invoke(Object receiver, Object... args)
    507             throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    508         if (args == null) {
    509             args = EmptyArray.OBJECT;
    510         }
    511         return invokeNative(receiver, args, declaringClass, parameterTypes, returnType, slot, flag);
    512     }
    513 
    514     private native Object invokeNative(Object obj, Object[] args, Class<?> declaringClass,
    515             Class<?>[] parameterTypes, Class<?> returnType, int slot, boolean noAccessCheck)
    516                     throws IllegalAccessException, IllegalArgumentException,
    517                             InvocationTargetException;
    518 
    519     /**
    520      * Returns a string containing a concise, human-readable description of this
    521      * method. The format of the string is:
    522      *
    523      * <ol>
    524      *   <li>modifiers (if any)
    525      *   <li>return type or 'void'
    526      *   <li>declaring class name
    527      *   <li>'('
    528      *   <li>parameter types, separated by ',' (if any)
    529      *   <li>')'
    530      *   <li>'throws' plus exception types, separated by ',' (if any)
    531      * </ol>
    532      *
    533      * For example: {@code public native Object
    534      * java.lang.Method.invoke(Object,Object) throws
    535      * IllegalAccessException,IllegalArgumentException
    536      * ,InvocationTargetException}
    537      *
    538      * @return a printable representation for this method
    539      */
    540     @Override
    541     public String toString() {
    542         StringBuilder result = new StringBuilder(Modifier.toString(getModifiers()));
    543 
    544         if (result.length() != 0)
    545             result.append(' ');
    546         result.append(returnType.getName());
    547         result.append(' ');
    548         result.append(declaringClass.getName());
    549         result.append('.');
    550         result.append(name);
    551         result.append("(");
    552         result.append(toString(parameterTypes));
    553         result.append(")");
    554         if (exceptionTypes != null && exceptionTypes.length != 0) {
    555             result.append(" throws ");
    556             result.append(toString(exceptionTypes));
    557         }
    558 
    559         return result.toString();
    560     }
    561 
    562     /**
    563      * Returns the constructor's signature in non-printable form. This is called
    564      * (only) from IO native code and needed for deriving the serialVersionUID
    565      * of the class
    566      *
    567      * @return The constructor's signature.
    568      */
    569     @SuppressWarnings("unused")
    570     private String getSignature() {
    571         StringBuilder result = new StringBuilder();
    572 
    573         result.append('(');
    574         for (int i = 0; i < parameterTypes.length; i++) {
    575             result.append(getSignature(parameterTypes[i]));
    576         }
    577         result.append(')');
    578         result.append(getSignature(returnType));
    579 
    580         return result.toString();
    581     }
    582 
    583 }
    View Code

    Modifier

      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 package java.lang.reflect;
     19 
     20 /**
     21  * This class provides static methods to decode class and member modifiers.
     22  *
     23  * @see Class#getModifiers()
     24  * @see Member#getModifiers()
     25  */
     26 public class Modifier {
     27 
     28     /**
     29      * The {@code int} value representing the {@code public}
     30      * modifier.
     31      */
     32     public static final int PUBLIC = 0x1;
     33 
     34     /**
     35      * The {@code int} value representing the {@code private}
     36      * modifier.
     37      */
     38     public static final int PRIVATE = 0x2;
     39 
     40     /**
     41      * The {@code int} value representing the {@code protected}
     42      * modifier.
     43      */
     44     public static final int PROTECTED = 0x4;
     45 
     46     /**
     47      * The {@code int} value representing the {@code static} modifier.
     48      */
     49     public static final int STATIC = 0x8;
     50 
     51     /**
     52      * The {@code int} value representing the {@code final} modifier.
     53      */
     54     public static final int FINAL = 0x10;
     55 
     56     /**
     57      * The {@code int} value representing the {@code synchronized}
     58      * modifier.
     59      */
     60     public static final int SYNCHRONIZED = 0x20;
     61 
     62     /**
     63      * The {@code int} value representing the {@code volatile}
     64      * modifier.
     65      */
     66     public static final int VOLATILE = 0x40;
     67 
     68     /**
     69      * The {@code int} value representing the {@code transient}
     70      * modifier.
     71      */
     72     public static final int TRANSIENT = 0x80;
     73 
     74     /**
     75      * The {@code int} value representing the {@code native} modifier.
     76      */
     77     public static final int NATIVE = 0x100;
     78 
     79     /**
     80      * The {@code int} value representing the {@code interface}
     81      * modifier.
     82      */
     83     public static final int INTERFACE = 0x200;
     84 
     85     /**
     86      * The {@code int} value representing the {@code abstract}
     87      * modifier.
     88      */
     89     public static final int ABSTRACT = 0x400;
     90 
     91     /**
     92      * The {@code int} value representing the {@code strict} modifier.
     93      */
     94     public static final int STRICT = 0x800;
     95 
     96     // Non-public types required by Java 5 update to class file format
     97     static final int BRIDGE = 0x40;
     98 
     99     static final int VARARGS = 0x80;
    100 
    101     static final int SYNTHETIC = 0x1000;
    102 
    103     static final int ANNOTATION = 0x2000;
    104 
    105     static final int ENUM = 0x4000;
    106 
    107     /**
    108      * Constructs a new {@code Modifier} instance.
    109      */
    110     public Modifier() {
    111     }
    112 
    113     /**
    114      * Returns a mask of all the modifiers that may be applied to classes.
    115      * @since 1.7
    116      * @hide 1.7
    117      */
    118     public static int classModifiers() {
    119         return PUBLIC | PROTECTED | PRIVATE | ABSTRACT | STATIC | FINAL | STRICT;
    120     }
    121 
    122     /**
    123      * Returns a mask of all the modifiers that may be applied to constructors.
    124      * @since 1.7
    125      * @hide 1.7
    126      */
    127     public static int constructorModifiers() {
    128         return PUBLIC | PROTECTED | PRIVATE;
    129     }
    130 
    131     /**
    132      * Returns a mask of all the modifiers that may be applied to fields.
    133      * @since 1.7
    134      * @hide 1.7
    135      */
    136     public static int fieldModifiers() {
    137         return PUBLIC | PROTECTED | PRIVATE | STATIC | FINAL | TRANSIENT | VOLATILE;
    138     }
    139 
    140     /**
    141      * Returns a mask of all the modifiers that may be applied to interfaces.
    142      * @since 1.7
    143      * @hide 1.7
    144      */
    145     public static int interfaceModifiers() {
    146         return PUBLIC | PROTECTED | PRIVATE | ABSTRACT | STATIC | STRICT;
    147     }
    148 
    149     /**
    150      * Returns a mask of all the modifiers that may be applied to methods.
    151      * @since 1.7
    152      * @hide 1.7
    153      */
    154     public static int methodModifiers() {
    155         return PUBLIC | PROTECTED | PRIVATE | ABSTRACT | STATIC | FINAL | SYNCHRONIZED | NATIVE | STRICT;
    156     }
    157 
    158     /**
    159      * Indicates whether or not the specified modifiers contain the {@code
    160      * abstract} modifier.
    161      *
    162      * @param modifiers
    163      *            the modifiers to test
    164      * @return {@code true} if the specified modifiers contain the {@code
    165      *         abstract} modifier, {@code false} otherwise
    166      */
    167     public static boolean isAbstract(int modifiers) {
    168         return ((modifiers & ABSTRACT) != 0);
    169     }
    170 
    171     /**
    172      * Indicates whether or not the specified modifiers contain the {@code
    173      * final} modifier.
    174      *
    175      * @param modifiers
    176      *            the modifiers to test
    177      * @return {@code true} if the specified modifiers contain the {@code
    178      *         final} modifier, {@code false} otherwise
    179      */
    180     public static boolean isFinal(int modifiers) {
    181         return ((modifiers & FINAL) != 0);
    182     }
    183 
    184     /**
    185      * Indicates whether or not the specified modifiers contain the {@code
    186      * interface} modifier.
    187      *
    188      * @param modifiers
    189      *            the modifiers to test
    190      * @return {@code true} if the specified modifiers contain the {@code
    191      *         interface} modifier, {@code false} otherwise
    192      */
    193     public static boolean isInterface(int modifiers) {
    194         return ((modifiers & INTERFACE) != 0);
    195     }
    196 
    197     /**
    198      * Indicates whether or not the specified modifiers contain the {@code
    199      * native} modifier.
    200      *
    201      * @param modifiers
    202      *            the modifiers to test
    203      * @return {@code true} if the specified modifiers contain the {@code
    204      *         native} modifier, {@code false} otherwise
    205      */
    206     public static boolean isNative(int modifiers) {
    207         return ((modifiers & NATIVE) != 0);
    208     }
    209 
    210     /**
    211      * Indicates whether or not the specified modifiers contain the {@code
    212      * private} modifier.
    213      *
    214      * @param modifiers
    215      *            the modifiers to test
    216      * @return {@code true} if the specified modifiers contain the {@code
    217      *         private} modifier, {@code false} otherwise
    218      */
    219     public static boolean isPrivate(int modifiers) {
    220         return ((modifiers & PRIVATE) != 0);
    221     }
    222 
    223     /**
    224      * Indicates whether or not the specified modifiers contain the {@code
    225      * protected} modifier.
    226      *
    227      * @param modifiers
    228      *            the modifiers to test
    229      * @return {@code true} if the specified modifiers contain the {@code
    230      *         protected} modifier, {@code false} otherwise
    231      */
    232     public static boolean isProtected(int modifiers) {
    233         return ((modifiers & PROTECTED) != 0);
    234     }
    235 
    236     /**
    237      * Indicates whether or not the specified modifiers contain the {@code
    238      * public} modifier.
    239      *
    240      * @param modifiers
    241      *            the modifiers to test
    242      * @return {@code true} if the specified modifiers contain the {@code
    243      *         public} modifier, {@code false} otherwise
    244      */
    245     public static boolean isPublic(int modifiers) {
    246         return ((modifiers & PUBLIC) != 0);
    247     }
    248 
    249     /**
    250      * Indicates whether or not the specified modifiers contain the {@code
    251      * static} modifier.
    252      *
    253      * @param modifiers
    254      *            the modifiers to test
    255      * @return {@code true} if the specified modifiers contain the {@code
    256      *         static} modifier, {@code false} otherwise
    257      */
    258     public static boolean isStatic(int modifiers) {
    259         return ((modifiers & STATIC) != 0);
    260     }
    261 
    262     /**
    263      * Indicates whether or not the specified modifiers contain the {@code
    264      * strict} modifier.
    265      *
    266      * @param modifiers
    267      *            the modifiers to test
    268      * @return {@code true} if the specified modifiers contain the {@code
    269      *         strict} modifier, {@code false} otherwise
    270      */
    271     public static boolean isStrict(int modifiers) {
    272         return ((modifiers & STRICT) != 0);
    273     }
    274 
    275     /**
    276      * Indicates whether or not the specified modifiers contain the {@code
    277      * synchronized} modifier.
    278      *
    279      * @param modifiers
    280      *            the modifiers to test
    281      * @return {@code true} if the specified modifiers contain the {@code
    282      *         synchronized} modifier, {@code false} otherwise
    283      */
    284     public static boolean isSynchronized(int modifiers) {
    285         return ((modifiers & SYNCHRONIZED) != 0);
    286     }
    287 
    288     /**
    289      * Indicates whether or not the specified modifiers contain the {@code
    290      * transient} modifier.
    291      *
    292      * @param modifiers
    293      *            the modifiers to test
    294      * @return {@code true} if the specified modifiers contain the {@code
    295      *         transient} modifier, {@code false} otherwise
    296      */
    297     public static boolean isTransient(int modifiers) {
    298         return ((modifiers & TRANSIENT) != 0);
    299     }
    300 
    301     /**
    302      * Indicates whether or not the specified modifiers contain the {@code
    303      * volatile} modifier.
    304      *
    305      * @param modifiers
    306      *            the modifiers to test
    307      * @return {@code true} if the specified modifiers contain the {@code
    308      *         volatile} modifier, {@code false} otherwise
    309      */
    310     public static boolean isVolatile(int modifiers) {
    311         return ((modifiers & VOLATILE) != 0);
    312     }
    313 
    314     /**
    315      * Returns a string containing the string representation of all modifiers
    316      * present in the specified modifiers. Modifiers appear in the order
    317      * specified by the Java Language Specification:
    318      *
    319      * {@code public private protected abstract static final transient volatile native synchronized interface strict}
    320      *
    321      * @param modifiers
    322      *            the modifiers to print
    323      * @return a printable representation of the modifiers
    324      */
    325     public static java.lang.String toString(int modifiers) {
    326         StringBuilder buf = new StringBuilder();
    327 
    328         if (isPublic(modifiers)) {
    329             buf.append("public ");
    330         }
    331         if (isProtected(modifiers)) {
    332             buf.append("protected ");
    333         }
    334         if (isPrivate(modifiers)) {
    335             buf.append("private ");
    336         }
    337         if (isAbstract(modifiers)) {
    338             buf.append("abstract ");
    339         }
    340         if (isStatic(modifiers)) {
    341             buf.append("static ");
    342         }
    343         if (isFinal(modifiers)) {
    344             buf.append("final ");
    345         }
    346         if (isTransient(modifiers)) {
    347             buf.append("transient ");
    348         }
    349         if (isVolatile(modifiers)) {
    350             buf.append("volatile ");
    351         }
    352         if (isSynchronized(modifiers)) {
    353             buf.append("synchronized ");
    354         }
    355         if (isNative(modifiers)) {
    356             buf.append("native ");
    357         }
    358         if (isStrict(modifiers)) {
    359             buf.append("strictfp ");
    360         }
    361         if (isInterface(modifiers)) {
    362             buf.append("interface ");
    363         }
    364         if (buf.length() == 0) {
    365             return "";
    366         }
    367         buf.setLength(buf.length() - 1);
    368         return buf.toString();
    369     }
    370 }
    View Code
    1. 运行期类型鉴定(RTTI)的概念初看非常简单——手上只有基础类型的一个句柄时,利用它判断一个对象的正确类型。一种是“传统”RTTI,它假定我们已在编译和运行期拥有所有类型;另一种是Java1.1特有的“反射”机制,利用它可在运行期独立查找类信息。
    2. In C++, dynamic_cast and typeid operator works only for class with virtual function. In fact, type_info is inserted in the first slot of vtble, if vtble exist.
    3. 为理解RTTI在Java里如何工作,首先必须了解类型信息在运行期是如何表示的。这时要用到一个名为“Class对象”的特殊形式的对象,其中包含了与类有关的信息(有时也把它叫作“元类”)。事实上,我们要用Class对象创建属于某个类的全部“常规”或“普通”对象。对于作为程序一部分的每个类,它们都有一个Class对象。换言之,每次写一个新类时,同时也会创建一个Class对象(更恰当地说,是保存在一个完全同名的.class文件中)。在运行期,一旦我们想生成那个类的一个对象,用于执行程序的Java虚拟机(JVM)首先就会检查那个类型的Class对象是否已经载入。若尚未载入,JVM就会查找同名的.class文件,并将其载入。所以Java程序启动时并不是完全载入的,这一点与许多传统语言都不同。一旦那个类型的Class对象进入内存,就用它创建那一类型的所有对象。
    4. Class.forName("Gum");
      该方法是Class(即全部Class所从属的)的一个static成员。而Class对象和其他任何对象都是类似的,所以能够获取和控制它的一个句柄(装载模块就是干这件事的)。为获得Class的一个句柄,一个办法是使用forName()。它的作用是取得包含了目标类文本名字的一个String(注意拼写和大小写)。最后返回的是一个Class句柄。
    5. Class.forName("Gum");
      该方法是Class(即全部Class所从属的)的一个static成员。而Class对象和其他任何对象都是类似的,所以能够获取和控制它的一个句柄(装载模块就是干这件事的)。为获得Class的一个句柄,一个办法是使用forName()。它的作用是取得包含了目标类文本名字的一个String(注意拼写和大小写)。最后返回的是一个Class句柄。
    6. RTTI在Java中存在三种形式。关键字instanceof告诉我们对象是不是一个特定类型的实例(Instance即“实例”)。它会返回一个布尔值,以便以问题的形式使用,就象下面这样:if(x instanceof Dog)
    7. 首先必须获得指向适当Class对象的的一个句柄。就象前例演示的那样,一个办法是用一个字串以及Class.forName()方法。这是非常方便的,因为不需要那种类型的一个对象来获取Class句柄。然而,对于自己感兴趣的类型,如果已有了它的一个对象,那么为了取得Class句柄,可调用属于Object根类一部分的一个方法:getClass()。它的作用是返回一个特定的Class句柄,用来表示对象的实际类型。
    8. 若从表面看,Class的newInstance()方法似乎是克隆(clone())一个对象的另一种手段。但两者是有区别的。利用newInstance(),我们可在没有现成对象供“克隆”的情况下新建一个对象。就象上面的程序演示的那样,当时没有Toy对象,只有cy——即y的Class对象的一个句柄。利用它可以实现“虚拟构建器”。换言之,我们表达:“尽管我不知道你的准确类型是什么,但请你无论如何都正确地创建自己。
    9. 如果不知道一个对象的准确类型,RTTI会帮助我们调查。但却有一个限制:类型必须是在编译期间已知的,否则就不能用RTTI调查它,进而无法展开下一步的工作。换言之,编译器必须明确知道RTTI要处理的所有类。
    10. 用“快速应用开发”(RAD)模型来构建程序项目。RAD一般是在应用程序构建工具中内建的。这是编制程序的一种可视途径(在屏幕上以窗体的形式出现)。可将代表不同组件的图标拖曳到窗体中。随后,通过设定这些组件的属性或者值,进行正确的配置。设计期间的配置要求任何组件都是可以“例示”的(即可以自由获得它们的实例)。这些组件也要揭示出自己的一部分内容,允许程序员读取和设置各种值。此外,用于控制GUI事件的组件必须揭示出与相应的方法有关的信息,以便RAD环境帮助程序员用自己的代码覆盖这些由事件驱动的方法。“反射”提供了一种特殊的机制,可以侦测可用的方法,并产生方法名。通过Java Beans(第13章将详细介绍),Java 1.1为这种基于组件的程序设计提供了一个基础结构。
    11. 在运行期查询类信息的另一个原动力是通过网络创建与执行位于远程系统上的对象。这就叫作“远程方法调用”(RMI),它允许Java程序(版本1.1以上)使用由多台机器发布或分布的对象。这种对象的分布可能是由多方面的原因引起的:可能要做一件计算密集型的工作,想对它进行分割,让处于空闲状态的其他机器分担部分工作,从而加快处理进度。某些情况下,可能需要将用于控制特定类型任务(比如多层客户/服务器架构中的“运作规则”)的代码放置在一台特殊的机器上,使这台机器成为对那些行动进行描述的一个通用储藏所。而且可以方便地修改这个场所,使其对系统内的所有方面产生影响(这是一种特别有用的设计思路,因为机器是独立存在的,所以能轻易修改软件!)。分布式计算也能更充分地发挥某些专用硬件的作用,它们特别擅长执行一些特定的任务——例如矩阵逆转——但对常规编程来说却显得太夸张或者太昂贵了。
    12. Class类(本章前面已有详细论述)得到了扩展,可以支持“反射”的概念。针对Field,Method以及Constructor类(每个都实现了Memberinterface——成员接口),它们都新增了一个库:java.lang.reflect。这些类型的对象都是JVM在运行期创建的,用于代表未知类里对应的成员。这样便可用构建器创建新对象,用get()和set()方法读取和修改与Field对象关联的字段,以及用invoke()方法调用与Method对象关联的方法。此外,我们可调用方法getFields(),getMethods(),getConstructors(),分别返回用于表示字段、方法以及构建器的对象数组(在联机文档中,还可找到与Class类有关的更多的资料)。因此,匿名对象的类信息可在运行期被完整的揭露出来,而在编译期间不需要知道任何东西。
    13. 通过“反射”同一个未知类型的对象打交道时,JVM只是简单地检查那个对象,并调查它从属于哪个特定的类(就象以前的RTTI那样)。但在这之后,在我们做其他任何事情之前,Class对象必须载入。因此,用于那种特定类型的.class文件必须能由JVM调用(要么在本地机器内,要么可以通过网络取得)。所以RTTI和“反射”之间唯一的区别就是对RTTI来说,编译器会在编译期打开和检查.class文件。换句话说,我们可以用“普通”方式调用一个对象的所有方法;但对“反射”来说,.class文件在编译期间是不可使用的,而是由运行期环境打开和检查。
    14. Class方法getMethods()和getConstructors()可以分别返回Method和Constructor的一个数组。每个类都提供了进一步的方法,可解析出它们所代表的方法的名字、参数以及返回值。但也可以象这样一样只使用toString(),生成一个含有完整方法签名的字串。
  • 相关阅读:
    开博说两句
    学习总结 (持续更新)
    ip代理 120203
    [vs2005]关于预编绎网站的问题[已预编译此应用程序的错误]
    JAVA类基础
    集合类和泛型
    IO流——字符流
    多线程和包
    多态和内部类
    抽象类与接口
  • 原文地址:https://www.cnblogs.com/iiiDragon/p/3272192.html
Copyright © 2011-2022 走看看