天天看點

Java注解和反射,美團Java面試題庫

//實體類

class User{

private String name;

private int id;

private int age;



public User() {

}



public User(String name, int id, int age) {

    this.name = name;

    this.id = id;

    this.age = age;

}
           

}

**Class類**:一個Class對象寶華了特定某個結構的有關資訊



1.  Class對象隻能由系統建立

2.  一個加載的類在JVM中隻會有一個Class執行個體,一個Class對象對應的是一個加載到JVM中的.class檔案

3.  Class類是Reflection的根源,針對任何想動态加載的類,必須獲得Class對象



### [](https://gitee.com/vip204888/java-p7)2.1 擷取Class類的執行個體



1.  已知具體類,通過類的class屬性擷取,最安全,性能最高(Class c = Person.class;)

2.  已知某個類的執行個體,調用該執行個體的getClass()方法擷取Class對象(Class c = person.getClass()😉

3.  已知一個類的全類名,且該類在類路徑下,通過Class類的靜态方法forName() 擷取,需要抛出異常

4.  内置基本資料類型直接使用類名.Type

5.  利用ClassLoader



*   數組隻要元素類型與次元一樣,就是同一個class



[](https://gitee.com/vip204888/java-p7)2.2 Java 記憶體

----------------------------------------------------------------------



*   堆:存放new出來的對象和數組;可以被所有線程共享,不存放别的對象引用

    

*   棧:存放基本變量類型;存放引用對象的變量(此引用在堆的具體位址)

    

*   方法區:可以被所有線程共享;包含所有的class和static變量

    



類的加載過程:



1.  類的**加載(Load)**

    

    *   将class檔案位元組碼内容加載到記憶體中,并将這些靜态資料轉換成方法區的運作時資料結構,然後**生成一個代表該類的java.lang.Class對象**

    *   類加載器把類(class)裝載進記憶體。有**引導類加載器**(Bootstap Classloader)(JVM自帶,C++編寫,負責Java平台核心庫,無法直接擷取),**擴充類加載器**(Extension Classloader)(負責jre/lib/ext目錄下的jar包裝入工作庫),**系統類加載器**(System Classloader)(負責java -classpath所指的目錄下的類與jar包裝入,最常用的加載器)

    *   雙親委派機制確定類的正确加載

    

    ```

    //類加載器示範

    public class ClassLoaderDemo {

        public static void main(String[] args) throws ClassNotFoundException {

            //擷取系統類的加載器

            ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();

            System.out.println(systemClassLoader);

    

            //擷取系統類加載器的父類加載器--->擴充類加載器

            ClassLoader parent = systemClassLoader.getParent();

            System.out.println(parent);

    

            //擷取擴充類加載器的父類加載器-->根加載器

            ClassLoader parent1 = parent.getParent();

            System.out.println(parent1);

    

            //測試目前類是哪個加載器加載的

            ClassLoader classLoader = Class.forName("com.jayz.annotationDemo.ClassLoaderDemo").getClassLoader();

            System.out.println(classLoader);

    

            //測試JDK内置類加載

            classLoader = Class.forName("java.lang.Object").getClassLoader();

            System.out.println(classLoader);

    

            //擷取系統類加載器加載的路徑

            System.out.println(System.getProperty("java.class.path"));

        }

    } 

    ```

2.  類的連結(Link)

    

    *   将Java類的二進制代碼合并到JVM運作環境中

        *   驗證:確定加載的類資訊符合JVM規範,沒有安全問題

        *   準備:正式**為類變量(static)配置設定記憶體并設定類變量預設初始值**,記憶體都将在方法區中配置設定。

        *   解析:虛拟機常量池内的符号引用(常量名)替換為直接引用(位址)的過程

3.  類的初始化(Initialize)

    

    *   **執行類構造器()方法的過程。類構造器方法是由編譯器自動收集類中所有類變量的指派動作和靜态代碼塊中的語句合并産生**(不是類對象的構造器)

        

    *   初始化一個類時,若發現其父類還沒有初始化,先觸發其父類的初始化

        

    *   虛拟機保證一個類的()方法在多線程環境中被正确加鎖和同步。

        

    *   發生類的初始化(類的主動應用),被動引用不會。

        

        1.  主動引用:當虛拟機啟動時,先初始化main方法所在的類

        

        *   new 一個類的對象

        *   調用類的靜态方法和靜态成員

        *   使用java.lang.reflect包中的方法對類進行反射調用

        *   初始化一個類,若其父類沒有被初始化,先初始化父類

        

        2.  被動引用

            *   通路一個靜态域時,隻有真正聲明這個域的類才會被初始化(如子類引用父類的靜态變量,不會導緻子類初始化)

            *   通過數組定義類引用,不會觸發此類的初始化

            *   引用常量不會觸發初始化(常量在連結階段存入常量池)



           

public class InitiDemo {

static {

    System.out.println("Main所在類加載");

}



public static void main(String[] args) throws ClassNotFoundException {

    //1.主動引用

    //Son son = new Son(); //Main所在類加載 父類被加載 子類被加載



    // 反射

    //Class.forName("com.jayz.annotationDemo.Son");//Main所在類加載 父類被加載 子類被加載



    //被動引用

    //System.out.println(Son.b);//Main所在類加載 父類被加載 2

    Son[] sons = new Son[5]; //Main所在類加載

}
           

}

class Father{

static int b = 2;



static{

    System.out.println("父類被加載");

}
           

}

class Son extends Father{

static {

    System.out.println("子類被加載");

    m = 300;

}



static int m = 100;

static final int M = 1;
           

}

### [](https://gitee.com/vip204888/java-p7)2.3 類資訊



示例:擷取類相關資訊(方法,屬性,構造器,父類,接口,注解)



           

//擷取類的資訊

public class ClassInformation {

public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {

    Class c1 = Class.forName("com.jayz.annotationDemo.User");



    //獲得類的名字

    System.out.println(c1.getName()); //獲得包名+類名

    System.out.println(c1.getSimpleName()); //獲得類名



    //獲得類的屬性

    Field[] fields = c1.getFields(); //隻能找到 public 屬性

    fields = c1.getDeclaredFields(); //

    for(Field field:fields) {

        System.out.println(field);

    }



    //獲得指定屬性的值

    Field name = c1.getDeclaredField("name");

    System.out.println(name);



    //獲得類的方法

    Method[] methods = c1.getMethods(); //獲得本類及父類的所有public方法

    for(Method method:methods) {

        System.out.println(method);

    }

    methods = c1.getDeclaredMethods(); //獲得本類的所有方法

    for(Method method:methods) {

        System.out.println(method);

    }



    //獲得構造器方法

    Constructor constructor = c1.getConstructor();

    Constructor[] constructors = c1.getConstructors();

}
           

}

示例:\*\*通過反射構造對象,調用方法和屬性(私有的,setAccessible(true))。\*\*使用反射會影響程式效率。



           

//反射操作

public class ReflectionDemo02 {

public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {

    //獲得Class對象

    Class c1 = Class.forName("com.jayz.annotationDemo.User");



    //構造對象

    User u1 = (User)c1.newInstance();  //調用類的無參構造器,若定義了有參構造,沒有定義無參構造,無法使用此方法

    System.out.println(u1);



    //通過構造器建立對象

    Constructor constructor = c1.getConstructor(String.class, int.class, int.class);

    User u2 = (User)constructor.newInstance("jay", 01, 18);

    System.out.println(u2);



    //通過反射調用普通方法

    User u3 = (User)c1.newInstance();

    Method setName = c1.getDeclaredMethod("setName", String.class);



    //invoke 激活方法

    setName.invoke(u3,"jay2");

    System.out.println(u3.getName());



    //反射操作屬性

    User u4 = (User)c1.newInstance();

    Field name = c1.getDeclaredField("name");//通路私有屬性,權限不夠

    //關閉權限

    name.setAccessible(true);

    name.set(u4,"jay3");

    System.out.println(u4.getName());

}
           

}

### [](https://gitee.com/vip204888/java-p7)2.4 ORM (Object relation Mapping):利用注解和反射完成類和表結構的映射關系



           

public class ORM_Demo {

public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {

    Class c1 = Class.forName("com.jayz.annotationDemo.Student01");



    //通過反射獲得注解

    Annotation[] annotations = c1.getAnnotations();

    for (Annotation annotation : annotations) {

        System.out.println(annotation);

    }



    //獲得注解的 value的值

    TableJay tableJay = (TableJay)c1.getAnnotation(TableJay.class);

    String value = tableJay.value();

    System.out.println(value);



    //獲得類指定的注解

    Field name = c1.getDeclaredField("name");
           

結局:總結+分享

看完美團、位元組、騰訊這三家的一二三面試問題,是不是感覺問的特别多,可能咱們真的又得開啟面試造火箭、工作擰螺絲的模式去準備下一次的面試了。

開篇有提及我可是足足背下了Java網際網路工程師面試1000題,多少還是有點用的呢,換湯不換藥,不管面試官怎麼問你,抓住本質即可!能讀到此處的都是真愛,是以福利也為你準備,這份1000題免費送你!點選這裡免費領取

  • Java網際網路工程師面試1000題
Java注解和反射,美團Java面試題庫

而且從上面三家來看,算法與資料結構是必備不可少的呀,是以我建議大家可以去刷刷這本左程雲大佬著作的 《程式員代碼面試指南 IT名企算法與資料結構題目最優解》,裡面近200道真實出現過的經典代碼面試題。

  • 程式員代碼面試指南–IT名企算法與資料結構題目最優解
Java注解和反射,美團Java面試題庫
  • 其餘像設計模式,建議可以看看下面這4份PDF(已經整理)
Java注解和反射,美團Java面試題庫
  • 更多的Java面試學習筆記如下,關于面試這一塊,我額外細分出Java基礎-中級-進階開發的面試+解析,以及調優筆記等等等。。。
Java注解和反射,美團Java面試題庫

000題免費送你!點選這裡免費領取

  • Java網際網路工程師面試1000題

[外鍊圖檔轉存中…(img-86NjUafi-1628492561079)]

而且從上面三家來看,算法與資料結構是必備不可少的呀,是以我建議大家可以去刷刷這本左程雲大佬著作的 《程式員代碼面試指南 IT名企算法與資料結構題目最優解》,裡面近200道真實出現過的經典代碼面試題。

  • 程式員代碼面試指南–IT名企算法與資料結構題目最優解

[外鍊圖檔轉存中…(img-QrE74vYD-1628492561082)]

  • 其餘像設計模式,建議可以看看下面這4份PDF(已經整理)

[外鍊圖檔轉存中…(img-HxOlnooi-1628492561084)]

  • 更多的Java面試學習筆記如下,關于面試這一塊,我額外細分出Java基礎-中級-進階開發的面試+解析,以及調優筆記等等等。。。

[外鍊圖檔轉存中…(img-dy77T8jT-1628492561086)]

以上所提及的全部Java面試學習的PDF及筆記,如若皆是你所需要的,那麼都可發送給你!