1. 程式人生 > >一篇文章徹底搞懂Java的大Class到底是什麼

一篇文章徹底搞懂Java的大Class到底是什麼

作者在之前工作中,面試過很多求職者,發現有很多面試者對Java的 `Class` 搞不明白,理解的不到位,一知半解,一到用的時候,就不太會用。 因為自己本身以前剛學安卓的時候,甚至做安卓2,3年後,也是對 java的 `Class`不是太清楚,所以想寫一篇關於Java `Class` 的文章,沒有那麼多專業名詞,希望用通俗的語言能把Java的 `Class` 這個概念講明白,理解了`Class`後,Java的反射也就好理解多了。 `Class`很容易,保證看了就明白,我們先來熟悉一個最基礎的概念,什麼是類? ## 什麼是類? 這個想必所有的學過面向物件程式語言的同學應該都知道,下面給出正式一點的描述 **類就是具備某些共同特徵的實體的集合** 比如下面定義一個 Student 類 ```java class Student{ String name; int age; public void learn(){ System.out.println("正在學習"); } public int getAge(){ return age; } public void hello(String message){ System.out.println(message); } } ``` 所有的學生都有一姓名,都有年齡,都要去學習,這些都學生的共性 那麼既然所有的學生都有一些公共的特性,那麼我們Java(其它語言也一樣)語言中,所有的類是不是也都有公共的特性呢? 是不是不太明白?所有的類都有公共的特性? 是的?沒聽錯 我們再定義一個類`Book`,如下 ``` class Book{ private float price; private String author; } ``` 所有的書都有 價格,作者等公共的特性(這裡為了簡單,例子儘可能程式碼少點) 所以,不管是上面的`Student`,`Book`類,還是Java語言中的自帶類比如`String`類 所有的類,都有下面的一些共性: - 所有的類,都有一個類名:比如上面的 `Student`, `Book`, `String`類,再加上包名,假如包名是 com.test , 那麼這些類的名字就是 `com.test.Student` , `com.test.Book`, `com.test.String` - 所有的類,都有0個或者多個欄位,比如上面的 `name`,`age`,`price`,`author` - 所有的類,都有0個或者多個方法,比如上面的`learn()` - 所有的類,都有修飾符,比如`public`,`private`,`protected`等 - 所有的類,都有0個或者多個靜態方法 - 等等等 ## Class到底是什麼? 通過上面的分析我們知道,所有的類都有一些公共特性,那麼我們就定義一個類,來描述這些公共特性,我們暫且把這個類起個類名,叫 `Info` 其實我們這裡的Info類,就是java中的Class,java中的`Class`其實就是個普通的類而已,和其它的類沒什麼不一樣的。不信看看`Class`定義 ![image](https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/7a4d700724da0902b7bdf482487d3ea8.png) 是不是就是一個普通的類,我們把繼承關係去掉,是不是就是下面這樣了 ```java public class Class { .... } ``` 可不就是個普通的類嘛,只不過類名也叫`Class`,和java中的關鍵字`class`,只是首字母大寫了而已,要我說當初就不應該起名叫`Class`,應該叫`Type`,就不會有那麼多人誤解了,就不會有人把`Class`,`class`這兩個弄的暈頭轉向的傻傻分不清了。 > 總之一句話:Class就是一個普通的類,這個類描述的是所有的類的公共特性 ## Class類能幹什麼? 瞭解Class類能幹什麼之前,我們先來擴充套件一些其它的東西 既然上面我們知道了,所有的類都是有公共特性的,我們定義了一個叫`Class`的類來描述這些公共特性 **那麼是不是所有的類的方法,所有的類的欄位,是不是也有公共的特性?** 答案`是的` 是不是有點迷糊? 不要怕,很簡單,舉個例子就知道了。 還是上面的`Student`,`Book`類, - 所有的類的欄位,都有名字。 比如`Book`類中的`price`欄位,它的名字是不是`"price"` - 所有的類的欄位,都有型別。 比如`Book`類中的`price`欄位,它的型別是 `float` - 所有的類的欄位,都有修飾符。 比如`Book`類中的`price`欄位,它的修飾符是 `private` **所以這些類的欄位公共的特性,我們也可以定義一個類來描述,這個類就是Field** 我們看一下JDK中關於Field的定義 ![image](https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/0e5edf62b4cdfd1d54ad5cf6e0c6c66c.png) 是不是和`Class`類一樣,`Field`類也是一個普通的類 **同理,類中所有的方法,是不是也有公共的特性?** 答案:`是的` - 所有的類的方法,都有方法名 比如`Student`類中的`getAge()`方法,它的方法名是 `"getAge"` - 所有的類的方法,都有返回值型別 比如`Student`類中的`getAge()`方法,它的返回值是 `int`型別 - 所有的類的方法,都有引數。(無引數也是算是特殊的引數吧) 比如`Student`類中的`hello(String message)`方法,有一個引數,引數的型別是值是 `String`型別 - 所有類的方法,都有修飾符號。 比如`Student`類中的`getAge()`方法,它修飾符號是 `public` **所以這些類的方法的公共的特性,我們也可以定義一個類來描述,這個類就是Method** 我們看下JDK中的定義 ![image](https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/673cff8f642d9e9021b85e922e9d5d63.png) 同樣是一個普通的類 由上面可以,那麼`Class`類就是通過`Field`和`Method`來描述類中的欄位和方法 我們來看一下JDK中`Class`類中,關於Field和`Method`的成員 ![image](https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/5aa5f0ea4074e0768440d55e16dc6737.png) 這些陣列就是儲存類中的欄位或者方法的。 **扯遠了,回到開頭,Class類能幹什麼?** 既然通過上面我們知道了,Class類中儲存的是所有類的公共特性,那麼是不是我們通過Class知道某個類中有多少方法,有多少欄位,每個欄位叫什麼名字,每個欄位的型別是什麼,每個方法的方法名是什麼,某個方法有幾個引數,等等 答案`是肯定的` 那如何通過Class知道你說的這些資訊呢? 當然是寫程式碼啊,比如我們在程式執行的時候,點選某個按鈕,打印出某個類的資訊,是可以做到的 ## Class如何使用? 既然上面我們知道了`Class`能幹什麼了?下面我們簡單的瞭解一下,如何使用`Class` #### 如何使用Class? Class就是一個普通的類啊,使用普通的類就是建立一個物件,才能使用啊 很簡單啊,我們建立一個Class的物件就行了啊,就可以呼叫物件的各種方法了啊 使用就是這麼簡單 #### 如何獲取一個Class的物件? 我們先看一下JDK中 `Class`類的建構函式 ![image](https://img-hello-world.oss-cn-beijing.aliyuncs.com/imgs/6042663a6e45b420672fb7c199172101.png) 就這一個建構函式,還是私有的,所以,我們不能直接`new`一個物件了 **如何獲取一個Class的物件?** 答案:有以下`3`種方法,直接上程式碼 ```java public static void main(String[] args){ //第一種 Class c1 = String.class; //第二種 String s = "hello,world"; Class c2 = s.getClass(); //第三種,以上面的Book類為例,其實就是動態載入類,注意捕獲異常,因為類有可能不存在 try { Class c3 = Class.forName("com.test.Book"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } ``` #### 有了 Class的物件我們怎麼用 我們直接通過一個demo來演示更加的直接,如下 ```java package com.example.demo; public class Student { private String name; private int age; public static void main(String[] args){ //一般我們把Class的物件叫位元組碼 Class c = Student.class; // 外部普通類 System.out.println("Student類名是:" + c.getName()); System.out.println("Student類的簡單類名是:" + c.getSimpleName()); System.out.println("Student類有" + c.getDeclaredFields().length + "個欄位"); /** * .... * 我們可以通過 c (也就是Student這個類的物件,或者你也可以叫做Student類的位元組碼) * 拿到Student類中所有的方法名,方法數,欄位名,欄位數量,甚至你還可以通過Method來呼叫方法 * 只要查查API,熟悉了API,就能做到 * 暫時我們只打印簡單 */ } } ``` 總結一下: 綜上所述,我們知道了 - Class就是一個普通的類,就是用來描述一個類的資訊的(比如類有幾個欄位,幾個方法,名字叫什麼等等 ) - 可以通過 3 種方法來獲取Class的物件,也就是某個類的位元組碼 - 有個某個類的位元組碼以後,我們就知道知道這個類的許多資訊了 - Class一般是在執行時使用,你只要告訴我類名,我就可以知道這個類中有多少方法,有多少欄位,怎麼呼叫等等 - Filed,Method(還有其它的,我們只說這2個),分別是描述類的欄位和類的方法的 關於 Class 的知識就講到這裡,主要是明白 Class 到底是個什麼東西,剩下的就自己查一下API,寫個demo測試一下就行了。 希望這篇文章能給讀者帶來幫忙