類的定義 面向過程 :是一種以過程為中心的編程思想,實現功能的每一步,都是自己實現的 面向對象 :是一種以對象為中心的編程思想,通過指揮對象實現具體的功能 類的理解 類是對現實生活中一類具有共同屬性和行為的事物的抽象 類是對象的數據類型,類是具有相同屬性和行為的一組對象的集合 簡單理解:類就是對現實 ...
類的定義
面向過程 :是一種以過程為中心的編程思想,實現功能的每一步,都是自己實現的
面向對象 :是一種以對象為中心的編程思想,通過指揮對象實現具體的功能
-
類的理解
- 類是對現實生活中一類具有共同屬性和行為的事物的抽象
- 類是對象的數據類型,類是具有相同屬性和行為的一組對象的集合
- 簡單理解:類就是對現實事物的一種描述
-
類的組成
- 屬性:指事物的特征,例如:手機事物(品牌,價格,尺寸)
- 行為:指事物能執行的操作,例如:手機事物(打電話,發簡訊)
-
類和對象的關係
- 類:類是對現實生活中一類具有共同屬性和行為的事物的抽象
- 對象:是能夠看得到摸的著的真實存在的實體
- 簡單理解:類是對事物的一種描述,對象則為具體存在的事物
類的定義
public class Student { //定義一個公共類,都可以訪問調用該類
// 屬性 : 姓名, 年齡
// 成員變數: 跟之前定義變數的格式一樣, 只不過位置發生了改變, 類中方法外
String name;
int age;
// 行為 : 學習
// 成員方法: 跟之前定義方法的格式一樣, 只不過去掉了static關鍵字.
public void study(){
System.out.println("學習");
}
}
對於一個類來說,有三種成員:屬性 field、方法 method、構造器 constructor。
屬性(field 成員變數)
屬性用於定義該類或該類對象包含的數據或者說靜態特征。屬性作用範圍是整個類體。
在定義成員變數時可以對其初始化,如果不對其初始化,Java 使用預設的值對其初始化。
數據類型 | 預設值 |
整型 | 0 |
浮點型 | 0.0 |
字元型 | '\u0000' |
布爾型 | false |
所有引用類型 | null |
屬性定義格式:
[修飾符] 屬性類型 屬性名 = [預設值] ;
方法
方法用於定義該類或該類實例的行為特征和功能實現。方法是類和對象行為特征的抽象。面向對象中,整個程式的基本單位是類,方法是從屬於類和對象的。
[修飾符] 方法返回值類型 方法名(形參列表) {
// n 條語句
}
構造方法(構造器 constructor)
構造器用於對象的初始化
聲明格式:
[修飾符] 類名(形參列表){
//n 條語句
}
構造器 4 個要點:
- 構造器通過 new 關鍵字調用!!
- 構造器雖然有返回值,但是不能定義返回值類型(返回值的類型肯定是本類),不能在構造器里使用 return 返回某個值。
- 如果我們沒有定義構造器,則編譯器會自動定義一個無參的構造方法。如果已定義則編譯器不會自動添加!
- 構造器的方法名必須和類名一致
/*
定義一個“點”(Point)類用來表示二維空間中的點(有兩個坐標)。要求如下:
可以生成具有特定坐標的點對象。
提供可以計算該“點”距另外一點距離的方法。
*/
class Point { // 定義一個類
double x, y; // 屬性
public Point(double _x, double _y) { // 有參構造方法
x = _x;
y = _y;
}
public double getDistance(Point p) { //一個成員方法,返回類型為double
return Math.sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
}
public static void main(String[] args) { // 入口
Point p1 = new Point(3.0, 4.0);
Point origin = new Point(0.0, 0.0);
System.out.println(p1.getDistance(origin));
}
}
構造方法的重載
構造方法重載(創建不同用戶對象)
構造方法重載(創建不同用戶對象)
public class User {
int id; // id
String name; // 賬戶名
String pwd; // 密碼
public User() {
}
public User(int id, String name) {
this.id = id;
this.name = name;
}
public User(int id, String name, String pwd) { // 構造方法重載
this.id = id;
this.name = name;
this.pwd = pwd;
}
public static void main(String[] args) {
User u1 = new User();
User u2 = new User(101, "小七"); // 使用的是有兩個參數的構造方法
User u3 = new User(100, "張三", "123456"); // 使用的是三個參數的構造方法
}
}
回顧方法重載:
- 指同一個類中定義的多個方法之間的關係,滿足下列條件的多個方法相互構成重載
- 多個方法在同一個類中
- 多個方法具有相同的方法名
- 多個方法的參數不相同,類型不同或者數量不同
特點:
- 類型不同或者數量不同重載僅對應方法的定義,與方法的調用無關,調用方式參照標準格式
- 重載僅針對同一個類中方法的名稱與參數進行識別,與返回值無關,換句話說不能通過返回值來判定兩個方法是否相互構成重載
對象的創建和使用
創建對象的格式:
類名 對象名 = new 類名();
調用成員的格式:
對象名.成員變數
對象名.成員方法();
示例代碼 :
類的使用
public class TestStudent {
/*
創建對象的格式:
類名 對象名 = new 類名();
調用成員變數的格式:
對象名.變數名
調用成員方法的格式:
對象名.方法名();
*/
public static void main(String[] args) {
// 類名 對象名 = new 類名();
Student stu = new Student();
// 對象名.變數名
// 預設初始化值
System.out.println(stu.name); // null
System.out.println(stu.age); // 0
stu.name = "張三";
stu.age = 23;
System.out.println(stu.name); // 張三
System.out.println(stu.age); // 23
// 對象名.方法名();
stu.study();
// com.itheima.object1.Student@b4c966a
// 全類名(包名 + 類名)
System.out.println(stu);
}
}
對象記憶體圖
單個對象記憶體圖
多個對象記憶體圖
總結:
多個對象在堆記憶體中,都有不同的記憶體劃分,成員變數存儲在各自的記憶體區域中,成員方法多個對象共用的一份
JAVA 虛擬機記憶體模型概念
虛擬機棧(簡稱:棧)的特點如下:
1. 棧描述的是方法執行的記憶體模型。每個方法被調用都會創建一個棧幀(存儲局部變數、操作數、方法出口等)
2. JVM 為每個線程創建一個棧,用於存放該線程執行方法的信息(實際參數、局部變數等)
3. 棧屬於線程私有,不能實現線程間的共用!
4. 棧的存儲特性是“先進後出,後進先出”
5. 棧是由系統自動分配,速度快!棧是一個連續的記憶體空間!
堆的特點如下:
1. 堆用於存儲創建好的對象和數組(數組也是對象)
2. JVM 只有一個堆,被所有線程共用
3. 堆是一個不連續的記憶體空間,分配靈活,速度慢!
4. 堆被所有的線程所共用,在堆上的區域,會被垃圾回收器做進一步劃分,例如新生代、老年代的劃分。
方法區(也是堆)特點如下:
1. 方法區是 JAVA 虛擬機規範,可以有不同的實現。
i. JDK7 以前是“永久代”
ii. JDK7 部分去除“永久代”,靜態變數、字元串常量池都挪到了堆記憶體中
iii. JDK8 是“元數據空間”和堆結合起來。
2. JVM 只有一個方法區,被所有線程共用!
3. 方法區實際也是堆,只是用於存儲類、常量相關的信息!
4. 用來存放程式中永遠是不變或唯一的內容。(類信息【Class 對象,反射機制中會重點講授】、靜態變數、字元串常量等)
5. 常量池主要存放常量:如文本字元串、final 常量值。
多個對象指向相同記憶體圖
總結 :
當多個對象的引用指向同一個記憶體空間(變數所記錄的地址值是一樣的)
只要有任何一個對象修改了記憶體中的數據,隨後,無論使用哪一個對象進行數據獲取,都是修改後的數據。
成員變數和局部變數
成員變數和局部變數的區別
- 類中位置不同:成員變數(類中方法外)局部變數(方法內部或方法聲明上)
- 記憶體中位置不同:成員變數(堆記憶體)局部變數(棧記憶體)
- 生命周期不同:成員變數(隨著對象的存在而存在,隨著對象的消失而消失)局部變數(隨著方法的調用而存在,醉著方法的調用完畢而消失)
- 初始化值不同:成員變數(有預設初始化值)局部變數(沒有預設初始化值,必須先定義,賦值才能使用)
垃圾回收原理和演算法
記憶體管理
Java 的記憶體管理很大程度就是:堆中對象的管理,其中包括對象空間的分配和釋放。
對象空間的分配:使用 new 關鍵字創建對象即可
對象空間的釋放:將對象賦值 null 即可
垃圾回收過程
任何一種垃圾回收演算法一般要做兩件基本事情:
1. 發現無用的對象
2. 回收無用對象占用的記憶體空間。
垃圾回收機制保證可以將“無用的對象”進行回收。
無用的對象指的就是沒有任何變數引用該對象。Java 的垃圾回收器通過相關演算法發現無用對象,併進行清除和整理。
垃圾回收相關演算法
引用計數法
堆中的每個對象都對應一個引用計數器,當有引用指向這個對象時,引用計數器加1,而當指向該對象的引用失效時(引用變為 null),引用計數器減 1,最後如果該對象的引用計算器的值為 0 時,則 Java 垃圾回收器會認為該對象是
無用對象並對其進行回收。優點是演算法簡單,缺點是“迴圈引用的無用對象”無法別識別。
this 關鍵字
普通方法中,this 總是指向調用該方法的對象。
構造方法中,this 總是指向正要初始化的對象。
this()調用重載的構造方法,避免相同的初始化代碼。但只能在構造方法中用,並且必須位於構造方法的第一句。
this 不能用於 static 方法中。
this 是作為普通方法的“隱式參數”,由系統傳入到方法中。
this的用法詳解
public class TestThis {
int a, b, c;
TestThis() {
System.out.println("正要初始化一個Hello對象");
}
TestThis(int a, int b) {
// TestThis(); //這樣是無法調用構造方法的!
this(); // 調用無參的構造方法,並且必須位於第一行!
a = a;// 這裡都是指的局部變數而不是成員變數
// 這樣就區分了成員變數和局部變數. 這種情況占了this使用情況大多數!
this.a = a;
this.b = b;
}
TestThis(int a, int b, int c) {
this(a, b); // 調用帶參的構造方法,並且必須位於第一行!
this.c = c;
}
void sing() {
}
void eat() {
this.sing(); // 調用本類中的sing();
System.out.println("你媽媽喊你回家吃飯!");
}
public static void main(String[] args) {
TestThis hi = new TestThis(2, 3);
hi.eat();
}
}
this記憶體原理
註意 : this代表當前調用方法的引用,哪個對象調用的方法,this就代表哪一個對象
static 關鍵字
靜態變數/靜態方法生命周期和類相同,在整個程式執行期間都有效。它有如下特點:
為該類的公用變數,屬於類,被該類的所有實例共用,在類載入時被初始化。
static 變數只有一份。
一般用“類名.類變數/方法”來調用。
在 static 方法中不可直接訪問非 static 的成員。
static 關鍵字的使用
public class TestStatic {
int id; // id
String name; // 賬戶名
String pwd; // 密碼
static String company = "北京xxx"; // 公司名稱
public TestStatic(int id, String name) {
this.id = id;
this.name = name;
}
public void login() {
System.out.println(name);
}
public static void printCompany() {
// login();//調用非靜態成員,編譯就會報錯
System.out.println(company);
}
public static void main(String[] args) {
TestStatic u = new TestStatic(101, "高xx");
TestStatic.printCompany();
TestStatic.company = "北京阿裡";
TestStatic.printCompany();
}
}
靜態初始化塊
構造方法用於對象的普通屬性初始化。
靜態初始化塊,用於類的初始化操作,初始化靜態屬性。
在靜態初始化塊中不能直接訪問非 static 成員。
static 靜態初始化塊
public class TestStatic2 {
static String company; // 公司名稱
static {
System.out.println("執行類的初始化工作");
company = "北京xxx";
printCompany();
}
public static void printCompany() {
System.out.println(company);
}
public static void main(String[] args) {
}
}
包機制(package、import)
包(package)相當於文件夾對於文件的作用。用於管理類、用於解決類的重名問題。
package 的使用有兩個要點
1. 通常是類的第一句非註釋性語句。
2. 包名:功能變數名稱倒著寫即可,便於內部管理類。
com.oracle.test;
com.itbaizhan.gao.test;
com.itbaizhan.gao.view;
JDK 中的主要包
導入類 import
如果要使用其他包的類,需使用 import,從而在本類中直接通過類名來調用,否則就需要書寫類的完整包名和類名。
Java 會預設導入 java.lang 包下所有的類,因此這些類我們可以直接使用。
如果導入兩個同名的類,只能用包名+類名來顯示調用相關類:
java.util.Date date = new java.util.Date()
靜態導入
靜態導入(static import): 其作用是用於導入指定類的靜態屬性和靜態方法,這樣我們可以直接使用靜態屬性和靜態方法。
靜態導入的使用
package com.itbaizhan;
import static java.lang.Math.*;//導入Math類的所有靜態屬性
import static java.lang.Math.PI;//導入Math類的PI屬性
public class Test2 {
public static void main(String[] args) {
System.out.println(PI);
System.out.println(random());
}
}