## static && final
### static
:::success
static關鍵字用於表示一個成員變數或者方法屬於類別本身,而不是類別的instance-level。這意味著,不論我們創建多少個類別的object,靜態變數都只有一份資料,所有objectobject共享該靜態變數。
:::
:::info
static :一開始就畫記憶體位,全部只有一份(class level)
non static:執行到才畫記憶體位址。
加上static後,只會在記憶體存在一份,所有的物件共用這一份。(class level
:::
```=java=
public class MyClass {
private int nonStaticVariable;
public static void staticMethod() {
System.out.println(nonStaticVariable); // 這行會導致編譯錯誤
}
}
```
:::danger
=>class level(static)不能存取instance level(non-static)的method
=>instance level 可以存取class level (static)的method
:::
:question: 當staticMethod被調用時,nonStaticVariable可能還未被初始化?為什麼說"可能”呢?有什麼情況會已被初始化了呢?
```
ans:在調用之前已經有該class的物件被new出來,並透過物件的屬性調用
```
:::warning
### extra:
Java 的變數依照其存活時間長短分成下列四種:
**1. 類別變數 (Class Variables):**
* 在class 宣告static的變數,存活時間最長, 編譯時即配置記憶體存放於static區
* 有預設值
**2. 實體變數(Instant Variables):**
* 物件的屬性,沒有宣告static
* 於物件建立時產生, 存放於 heap 區, 只要物件未消滅皆可存取.
* 有預設值
**3. 方法變數 (Method Variables):**
* method的參數、method內定義的變數
* 放在stack
* 無預設值
* ==屬於local variables==
**4. 區塊變數 (Local Variables):**
* 即 if, switch, for, while, do-while 等流程控制語法大括弧內所定義之變數
* 放在stack,只能在該語法區塊內存取,
```=java
for(int i =0...){
dosomething
}
for(int i =1...){
dosomething
}
```
* 無預設值
* ==屬於local variables==
::::
### final
:::success
final關鍵字用於表示一個變數是read-only的,如果一個變數被final修飾,那麼它只能被賦值一次,賦值後其值就不能再被改變。
:::
```=java
public static void main(String[] args) {
final int X=5;
X=10; //error
}
```
::::success
如果一個方法被final修飾,那麼它不能被子類別重寫(能被子類別繼承)。
::::
```=java
class Animal{
final void makesound(){
System.out.println("Some generic sound");
}
public void eat(){
System.out.println("eat");
}
}
class Dog extends Animal{
public void makesound(){ //error
System.out.println("Dog sound");
}
}
```
:::success
如果一個類別被final修飾,那麼它不能被繼承。
:::
```=java
final class Animal{
void makesound(){
System.out.println("Some generic sound");
}
public void eat(){
System.out.println("eat");
}
}
class Dog extends Animal{ //error
....
}
```
## object(物件)
==java所有的物件都繼承自java.lang.Object (所有的class都繼承自java.lang.Object)==
### .equals()
:::success
在Java中,如果想要比較兩個物件是否完全相等,我們需要覆寫或實作 equals() 方法,而非使用 == 運算符號。
:::
:::warning
'= ='比較的是兩個物件的記憶體位值
'.equals()'比較的是兩個物件的內容
但,.equals()如果沒有經過覆寫,則會使用java.lang.Object(父類別)的.equals(),就跟'= ='一樣。
:::
```=java=
code
```
:::warning
**tips:**
我們在String中可以直接使用.equals()比較內容是因為在String class中已經對.equals()覆寫了。

:::
[來源](https://blog.csdn.net/wwwwwwwl/article/details/75187869?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-1-75187869-blog-110070231.235^v43^pc_blog_bottom_relevance_base8&spm=1001.2101.3001.4242.2&utm_relevant_index=4)
### getclass()
::::success
這個方法用來取得該物件的 Class 物件,該 Class 物件代表了該物件的實際類別(class)
::::
```=java=
public static void main(String[] args) {
String str = "Hello, world!";
Class<?> strClass = str.getClass();
System.out.println("The class of str is " + strClass.getName());
}
//Class<?> 表示的是一個未知類型的 Class object。
```
```
output:
The class of str is java.lang.String
```
### clone()
:::success
在Java中,Object類別提供了一個clone()方法,可以用來創建並返回該物件的一個副本。這個方法預設提供的是shallow copy,稱之為淺層拷貝
:::
#### shallow
如果是一個物件內的元素使用.clone()的話,則會複製該物件內元素的reference(ref 也是一種value)
```
review:在一個物件的屬性
String name="zhang"; //'name'為'zhang'這個物件的reference
```
會被複製的便是'name',但兩個name都指向同個物件"zhang"
物件"zhang"並沒有被複製。

[來源](https://blog.csdn.net/weixin_34334744/article/details/94113476?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-2-94113476-blog-107779427.235%5Ev43%5Epc_blog_bottom_relevance_base8&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-2-94113476-blog-107779427.235%5Ev43%5Epc_blog_bottom_relevance_base8&utm_relevant_index=5)
```=java=
public class ShallowCopyExample {
public static void main(String[] args) {
// 建立原始二維陣列
int[][] original = {{1, 2, 3}, {4, 5, 6}};
// 創建原始陣列的淺拷貝
int[][] copied = original.clone();
// 輸出原始陣列和複製陣列的第一個元素
System.out.println("Before modification:");
System.out.println("original[0][0] = " + original[0][0]);
System.out.println("copied[0][0] = " + copied[0][0]);
// 修改複製陣列的第一個元素
copied[0][0] = 100;
// 再次輸出原始陣列和複製陣列的第一個元素
System.out.println("After modification:");
System.out.println("original[0][0] = " + original[0][0]);
System.out.println("copied[0][0] = " + copied[0][0]);
}
}
```
```
output:
Before modification:
original[0][0] = 1
copied[0][0] = 1
After modification:
original[0][0] = 100
copied[0][0] = 100
```
:::info
'original' 跟'copied' 都指向{{1,2,3},{4,5,6}}這個二維陣列物件(同個address)
那從original去修改跟從copied去修改,都會造成共同的物件改變。
:::
:::danger
shallow並沒有new新的物件出來
再說一次,
String name="zhang";
int[][] original = {{1, 2, 3}, {4, 5, 6}};
等號右邊才是物件,左邊為ref
:::
#### deep copy
如果要連reference指向的物件都複製一份,稱為deep copy(深層拷貝)
要實現deep copy,就需要:
* 覆寫某個class 繼承自Object的.clone()方法
* 或是不覆寫,手動創立一個新物件
==共同點都是有新物件產生!!!==

```=java=
public class MyClass implements Cloneable {
private int[] array;
public MyClass(int[] array) {
this.array = array;
}
// Getter for array
public int[] getArray() {
return array;
}
@Override
public MyClass clone() {
int[] clonedArray = array.clone(); // This line creates a copy of the array. It is a primitive-type array and clone() can returned a array like deep-copy
return new MyClass(clonedArray); // new了一個新的物件,屬性相同,reference不同
}
}
```
```=java=
public class DeepCopyExample {
public static void main(String[] args) {
// 建立原始二維陣列
int[][] original = {{1, 2, 3}, {4, 5, 6}};
// 創建原始陣列的深層拷貝
int[][] copied = new int[original.length][];
for (int i = 0; i < original.length; i++) {
copied[i] = original[i].clone();
}
// 輸出原始陣列和複製陣列的第一個元素
System.out.println("Before modification:");
System.out.println("original[0][0] = " + original[0][0]);
System.out.println("copied[0][0] = " + copied[0][0]);
// 修改複製陣列的第一個元素
copied[0][0] = 100;
// 再次輸出原始陣列和複製陣列的第一個元素
System.out.println("After modification:");
System.out.println("original[0][0] = " + original[0][0]);
System.out.println("copied[0][0] = " + copied[0][0]);
}
}
```
```
output:
Before modification:
original[0][0] = 1
copied[0][0] = 1
After modification:
original[0][0] = 1
copied[0][0] = 100
```
:::info
因為兩個是分開的物件,所以改變不會互相影響。
:::
---
如果一個物件的元素是primitive type,則.clone()會複製它們的值並產生新物件。
```
int array[]={2,3,4};
int array2[]=array.clone();
System.out.println(array==array2);//false
```
:::success
<aside>
在Java中,物件元素是primitive type的clone()操作,會進行deep copy(深層拷貝),創建一個新的物件並複製所有的元素。
然而,對於Object[]陣列的clone(),則是shallow copy(淺層拷貝)。這是因為Object[]陣列的元素是reference型態,clone僅僅會複製這些reference,而不會複製reference所指向的物件。因此,原陣列和複製後的陣列中的元素會指向同一個物件。
</aside>
:::
:::danger
在使用.clone()的類別需要implements Cloneable:
public class MyClass implements Cloneable {}
否則會有CloneNotSupportedException
Cloneable介面在Java中是一種標記性介面(marker interface),它不包含任何方法,只是表明這個class的object可以被clone.
:::
:question: 在Java中,如果一個method被定義為private,請問它還可以被子類別override嗎
```
ans:不行,private在只能在同一個class存取,子類別無法override or inherit
```
:question: 那如果在子類別中定義了一樣的method name (argument也一樣),會怎麼樣呢?
```
ans:不會報錯,會視作子類別的新方法,看new的物件是哪個class,就用哪邊的方法。
```