[Think in Java]第2章 一切都是對象

来源:https://www.cnblogs.com/seanho/archive/2019/07/02/11123862.html
-Advertisement-
Play Games

[Think in Java]第2章 一切都是對象 如果我們說另一種不同的語言,那麼我們就會發覺有一個有些不同的世界 -- Luduing Wittgerstein 儘管Java基於C++,但相比之下,Java是一種更純粹的面向對象程式設計語言. Java語言假設我們只進行面向對象的程式設計(OOP ...


[Think in Java]第2章 一切都是對象

如果我們說另一種不同的語言,那麼我們就會發覺有一個有些不同的世界

-- Luduing Wittgerstein

儘管Java基於C++,但相比之下,Java是一種更純粹的面向對象程式設計語言.

Java語言假設我們只進行面向對象的程式設計(OOP)。

2.1 用引用操縱對象

每種語言都有自己操縱記憶體中元素的方式,1. 直接操縱 2. 或者基於某種特殊語法的間接表示。

java中,儘管一切都看作是對象了,但操作的標識符實際上是對象的一個引用(reference)

引用可以單獨存在,你擁有一個引用,並不一定需要有對象和它關聯。

 String s;

這裡創建了一個引用,並不是對象。如果此時向s發送消息,那麼會報運行時錯誤,因為它實際上並沒有和任何對象關聯。更加安全的做法是:創建一個引用的同時便進行初始化

 String good = “good”;

這種創建方式是java語言的一個特性:字元串可以用帶引號的文本初始化。更通用的方式是用new。

2.2 必須由你創建所有對象

一個引用被創建了,就希望它能與一個新的對象相關聯。通常用new操作符來實現這一目的,是以new關鍵字進行對象的初始化,new關鍵字的意思是:”給我一個新的對象”(上面的例子可以寫成)

 String good = new String("good");

表示: "給我一個新的字元串",而且通過提供一個初始字元串,給出了怎樣產生這個String的信息!

2.2.1 對象存儲到什麼地方

素質三連問:程式運行時,對象是怎麼進行放置安排的?記憶體是怎麼樣分配的?你個垃圾會嗎?

  1. 寄存器 最快的存儲區

  2. 棧 位於通用RAM

  3. 堆 通用記憶體池

  4. 常量存儲

  5. 非RAM存儲

(更加詳細的內容,參考《深入理解JVM》)

2.2.2 特例:基本類型 (由父標題推出:這些對象是Java已經幫你創建好了的)

基本類型之所以要特殊對待,是因為new將對象存儲在“堆“里,故用new創建一個對象——特別是小的,簡單的變數,往往不是很有效。因此,不用new創建變數,針對基本變數創建一個並非是引用的”自動“變數,這個變數直接存儲”值“,並置於棧中,因此更加高效。

java的基本類型的大小是固定的,這也是可移植性的原因之一!

需要註意的是 boolean 沒有確定大小,只有字面值 truefalse

 //這裡要有一張基本類型的總結圖

基本類型有著對應的包裝類,使得可以在對堆中創建一個非基本對象,用來表示對應的基本類型。

 char c = "x";
 Character ch = new Character(c);
 //或者
 Character ch = new Character("x");

Java SE5 有自動裝箱和拆箱的功能。

 Character ch = "x"; //基本類型轉換成包裝類型 ,裝箱
 char c = ch; //包裝類型反向轉換基本類型 ,拆箱
 //包裝類的後面再詳細介紹!

高精度數字 :以調用方法的形式進行運算,運算速度會比較慢;犧牲速度換取了精度!

  1. BigInteger

    支持任意精度的整數,不會丟失任何數據

  2. BigDecimal

    支持任何精度的定點數,例如貨幣匯率的計算!

2.2.3 Java中的數組

java中的數組需要被初始化,而且不能超出數據的範圍,這種範圍檢查需要以少量的記憶體開銷和運行時的下表檢查為代價的!但由此換來了安全性和效率的提高,小小的記憶體開銷可以說很值得了!

當創建一個數組對象時,就是創建了一個引用數組,並且引用都會自動被初始化為一個特定值,該值擁有自己的關鍵字null!一旦java看到了null,就知道這個引用還沒有指向某個對象,在使用任何引用時,都要為其指定一個對象! ( 關於數組更詳細的內容,見後面章節!)

2.3 永遠不要銷毀對象 (對應著JVM的垃圾回收機制)

2.3.1 作用域

作用域決定了在其內定義的變數名的可見性和生命周期!

註意代碼

 //這是c++,較大的作用域的變數可以”隱藏”!
 {
     int x = 12;
    {
         int x = 24; //在java中,非法的,x在之前已經被使用了
    }
 }

2.3.2 對象的作用域

java對象不具備和基本類型的生命周期。當用new創建了一個java對象時,它可以存活於作用域之外。

 {
     String s = new String("a String");
 }//end of scope

此時,引用s在作用域就是花括弧內,超過該區域無法再訪問這個對象,但是s指向的String對象仍繼續占據記憶體空間。

問題素質三連問:如何防止這些超過了作用域卻依舊存活在記憶體空間的對象撐爆你的記憶體,讓你的程式終止呢?

java有垃圾回收器(GC,garbige collector),用來監視用new創建的所有對象,那些不再被引用的對象的記憶體空間將會被釋放掉,以便給新對象使用!

吹一波java的垃圾回收機制:不需要關心對象的銷毀,消除了記憶體泄漏的顧慮一定程度上!

2.4 創建新的數據類型 :類

用class 關鍵字來聲明類

 class ATypeClass {   /*class body*/     }

用new來創建這個類型的對象

 ATypeClass a = new ATypeClass();

2.4.1 欄位和方法

類中有兩種元素: 1.欄位(也叫數據類型)和方法(也叫成員函數)

欄位可以是任意類型的對象,可以通過其引用與其進行通信,也可以是基本類型的一種。

如果欄位是某個對象的引用,那必須初始化該引用(就是用new一下)

每個對象都有其欄位空間;普通欄位不能在對象間共用。

 //定義一個類
 class DataOnly{
     int i;
     double d;
     boolean b;
 }
 //創建對象
 DataOnly dataOnly = new DataOnly();

給欄位賦值

 dataOnly.i = 47;
 dataOnly.d = 40.0;
 dataOnly.b = false;

給對象欄位賦值

 myPlane.leftTank.capacity = 100;

基本成員預設值

如果類的某個成員是基本數據類型,即使沒有初始化(既沒有new一下)java也會自動給它一個預設值。

基本類型預設值
boolean false
chat '\u0000'(null)
byte (byte)0
short (short)0
int 0
long 0.L
float 0.0f
double 0.0d

java會自動幫你初始化這些基本類型的成員變數,但是這種方法並不適用於局部變數(幾並非某個類的欄位)。如果某個方法中定義了:

 int x;

那麼變數x得到的可能是任意值,而不會被自動初始化為0,java在編譯時會返回一個錯誤,告訴你這個局部變數沒有初始化

2.5 方法,參數和返回值

方法的基本組成:名稱,參數,返回值,方法體

 ReturnType methodName( /* Argument list*/) {
     /*Method body*/
 }

返回類型:調用方法之後從方法返回的值

參數列表:要傳給方法的信息類型和名稱

方法簽名=方法名+參數列表 ,它唯一地標識出某個方法

方法是類的一部分,只能通過對象調用(當然也有直接類調用的,static方法就是針對類調用的,後詳解 見2.6.3)

方法調用方法:

 objectName.methodName(arg1,arg2);
 
 int x = a.f(); //向對象發送消息

返回值的類型必須要和x的類型相容!

2.5.1 參數列表

方法的參數列表指定要傳遞給方法什麼樣的信息,採用的都是對象的形式。在列表中指定對象的類型和名字,但這裡實際上傳遞的是對象的引用。

例子:接受String為參數,返回該字元串長度的兩倍

int storage(String s){
    return s.length()*2;
}

這裡s一旦傳遞給此方法,就可以把他當作其他對象一樣進行處理。如果不想返回任何值,

void nothing(){
 	/****/
}

2.6 構建一個Java程式

2.6.1 名字可見性

java使用包名來解決文件名字衝突的問題,創建名字空間來唯一確定一個類的位置

net.mindview.utility.fobiles

com.sean.Intruduce.class

2.6.2 運用其他構件(導入其他包內的類)

使用import關鍵字

import java.util.ArrayList; //導入指定某個類
import java.util.* //導入指定某個包下的所有類

2.6.3 static關鍵字

static 出現的兩種原因:

  1. 只想為某特定域分配單一存儲空間

  2. 即使沒創建對象,也能調用這個方法

在欄位前加上 static 就定義了一個靜態變數

class StaticTest{
    static int i = 47;
}
StaticTest st1 = new StaticTest();
StaticTest st2 = new StaticTest();

這裡的 st1.i和st2.i指向同一個存儲空間,具有相同的值48.//媽的,為什麼是48

static的引用方法

  1. 通過一個對象去定位它,st1.i;

  2. 通過類名直接引用,StaticTest.i;

 

對於方法而言,也是類似的。

class Person{
    staic void hello( ... );
}

引用方法:

//通過對象來調用靜態方法
Person p = new Person();
p.hello();

//類名直接調用靜態方法
Person.hello();

2.7 第一個java程式

//HelloDate.java
import java.util.*;
public class HelloDate{
    public static void main(String[] args){
        System.out.print("Hello. It's:");
        System.out.print(new Ddate());
    }
}

import關鍵字聲明要使用的包, java.lang是預設導入到每個java文件中的,所以他的類可以直接被使用.但是這裡java.lang裡面沒有Date類,所以得導入有Date類的包. 也可以具體的顯示導入哪個類

import java.util.Date

類的名字和文件名要相同.main

2.7.1編譯和運行

//編譯java文件
javac HelloDate.java

//運行
java HelloDate

2.8註釋和嵌入式文檔

// 這是當行註釋

/*
這是多行註釋...
這是多行註釋...
*/

/**
這是文檔註釋,開頭多了一個*號.
*/

 

2.8.1 註釋文檔

使用javadoc 來提取註釋以及特殊的標簽,並把相鄰的類和方法都抽取出來,輸出一個HTML文件,形成一份說明文檔

2.8.1 語法

javadoc的兩種方式

  1. 嵌入HTML

  2. 文檔標簽

獨立文檔標簽是用@開頭的命令,並且是在行首, 行內的@ 需要用花括弧內,才能視為標簽

註釋文檔的三種類型

  1. 類 位於類定義之前

  2. 域 域定義之前 (感覺叫變數註釋比較容易理解)

  3. 方法 方法定義之前

例子

/**這是類註釋*/
public class Documents{
    /**這是域註釋*/
    int i;
    /**這是方法註釋*/
    public void f(){.....}
}

需要註意的是:javadoc只能對public和protected成員進行文檔註釋, private和包內訪問成員的註釋會被忽略掉 (不過可以使用 -private 進行標記,達到被輸出的效果)

2.8.3 嵌入HTML

可以對註釋文檔加上html標簽進行格式上的優化,因為javadoc輸出的就是HTML文件格式

例如:

/**
*<pre>
*System.out,print(new Date());
*</pre>
*
*here is the list:
*<ol>
*<li> item one
*<li> item two
*</ol>
*/

不需要自己加標題 (h1,hr)之類的標簽,javadoc自己會生成標題.不然會衝突

 

2.8.4 一些標簽的實例

  1. @see 引用其他類

    格式:

    @see classname
    @see fuuly-qualified-classname
    @see fully-qualified-classname#method-name
    
  2. {@link package.class#member label}

    和@see類似, 用於行內,且用label作為超鏈接文本.

  3. {@docRoot} 生成到根目錄的相對路徑

  4. {@inheritDoc} 表示: 從當前這個類的最直接父類中繼承相關文檔到當前的文檔註釋中

  5. @version 版本信息

    格式: @version version-information

  6. @author 作者信息

  7. @since 最早的版本

  8. @param 用於方法中

    格式: @param parameter-name description

  9. @return

    格式: @return description ,用於描述返回值的含義

  10. @throws 拋出異常

  11. @deprecated

2.9 編碼風格

  1. 類名的首字母要大寫,如果幾個單片語成,把它們合在一起

    class AllTheColorsOfTheRainbow{....}

  2. 欄位以及對象引用名稱等,第一個字母採用小寫

    class AllTheColorsOfTheRainbow{
    	int anIntegerRepresentRainboow;
    	void changeTheValue(int newValue){....}
    }
    

     


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本人在 .NET 轉JAVA 的路上 ,也在學習SpringBoot相關知識,這裡記錄一下在Springboot中實現文件上傳下載的核心代碼 源碼下載地址: https://github.com/struggle0903/SpringBootfiledemo.git ...
  • 點擊屏幕拍打你的翅膀。當你飛過屏幕時,註意黑烏鴉。 下載地址 ...
  • 看一個數組的子集有多少,其實就是排列組合, 比如:[0,1] 對應的子集有:[] [0] [1] [1,1] 這四種。 一般對應有兩種方法: 位運算 和 回溯 。 這裡先使用位運算來做。 位運算 一個長度為n的數組,對其做排列組合,可以理解為:這n個數字中,有哪些是存在的,哪些是不存在的。 例如,數 ...
  • Python模塊和包 一、模塊 1. 什麼是模塊 常見的場景:一個模塊就是一個包含了Python定義和聲明的文件,文件名就是模塊名字加上.py的尾碼。 但其實import載入的模塊分為四個通用類別: 1 使用Python編寫的代碼(.py文件) 2 已被編譯為共用庫或DLL的C或C++擴展 3 包好 ...
  • 一、檢視一個函數相同的另一種方法 利用屬性:函數._name 從結果來看他們的本體都是hello函數 二、裝飾器 1.定義:在不改動代碼的基礎上無限擴展函數功能的一種機制,本質上來講,裝飾器是一個返回函數的高階函數。 2.裝飾器的使用:使用@愈發,即在每次要擴展到函數定義前使用@+函數名。 3.裝飾 ...
  • 個人網站: lipeiguan.top 以後會慢慢轉移到個人網站, 歡迎大家收藏^ . ^ 寫在前面 我們在開發一個網站的時候, 經常需要實現網站的用戶系統. 這個時候我們需要實現用戶註冊、用戶登錄、用戶認證、註銷、修改密碼等一系列功能. 如果我們都是自己實現的話, 不是不可以, 只是有些浪費時間. ...
  • 老雷socket編程之PHP利用socket擴展實現聊天服務 socket聊天服務原理 PHP有兩個socket的擴展 sockets和streamssockets socket_create(AF_INET, SOCK_STREAM, SOL_TCP) socket_write socket_re ...
  • 老雷socket編程之常見網路協議 1.ip IP協議是將多個包交換網路連接起來,它在源地址和目的地址之間傳送一種稱之為數據包的東西, 它還提供對數據大小的重新組裝功能,以適應不同網路對包大小的要求。 2.TCP 傳輸控制協議 TCP(Transmission Control Protocol 傳輸 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...