Head First Java學(xué)習(xí):第十章-數(shù)字很重要
?1、Math 方法:最接近全局的方法
一種方法的行為不依靠實例變量值,方法對參數(shù)執(zhí)行操作,但是操作不受實例變量狀態(tài)影響,那么為了執(zhí)行該方法去堆上建立對象實例比較浪費(fèi)。
舉例:
Math mathObject = new Math();
報錯:Math() has private access in java.lang.Math
而是可以直接使用:
int x = Math.round(43.4);
int y = Math.min(43,23);
int z = Math.abs(-34);
總結(jié):在Math這個類中的所有方法都不需要實例變量值。因為這些方法都是靜態(tài)的,所以無需Math的實例,你會用到的只有類本身。
2、非靜態(tài)方法與靜態(tài)方法的差別
當(dāng) 需要方法而不需要類的實例,那么可以用 static 關(guān)鍵字標(biāo)記出該。
使用 static 關(guān)鍵字標(biāo)記“不需要類實例的方法”,稱為“靜態(tài)方法”。
舉例:
public static int min(int a,int b){
//返回a與b中較小的值
}
如何調(diào)用:
- 以類的名稱調(diào)用靜態(tài)方法:min(88,43);
- 以引用變量的名稱調(diào)用非靜態(tài)的方法:
Song t = new Song();
t.play();
3、帶有靜態(tài)方法(static)的含義
抽象類(abstract修飾),不能創(chuàng)建出實例,即抽象的類不能被初始化。
非抽象的類如何限制初始化?
把構(gòu)造方法標(biāo)記為私有(private,只能被同一類的程序調(diào)用),則無法創(chuàng)建出類的實例,編譯器會知道不能存取這些私有的構(gòu)造函數(shù)。
不代表有一個或多個靜態(tài)方法的類不能被初始化,只要有main的類都有靜態(tài)方法。main()一般用來啟動或測試其他類,從main() 中創(chuàng)建類的實例并調(diào)用新實例上的方法。
在類中可以組合靜態(tài)方法和非靜態(tài)方法。非靜態(tài)方法都需要以某種實例操作,取得新對象的方法只有通過new或者序列化(deserialization)或者Java Reflection Api。
4、靜態(tài)方法調(diào)用其他方法和變量
第一:靜態(tài)方法不能調(diào)用非靜態(tài)的變量
靜態(tài)方法使用通過類的名稱來調(diào)用,不需要類的實例(不知道堆上有哪些實例),所以也無法引用到該類的任何實例變量,也不會知道可以使用哪個實例變量值。
如果調(diào)用非靜態(tài)的變量,會報錯:non-static variable size cannot be referenced from a static context
第二:靜態(tài)方法不能調(diào)用非靜態(tài)的方法
非靜態(tài)方法都是以實例變量的狀態(tài)來影響該方法的行為。調(diào)用非靜態(tài)方法,會在非靜態(tài)方法中用到實例變量,但是靜態(tài)方法無法引用該類的任何實例變量。
如果調(diào)用非靜態(tài)的方法,會報錯:non-static method getSize() cannot be referenced from a static context
5、靜態(tài)變量
靜態(tài)變量是共享的。
同一個類所有的實例共享一份靜態(tài)變量。
實例變量:每個實例一個
靜態(tài)變量:每個類一個,也叫類變量。類名.靜態(tài)變量名 存取
代碼舉例:
package chap10;
public class Duck {
private int size;
// 靜態(tài)變量只有在類第一次載入的時候被初始化
static int duckCount = 0;
// 構(gòu)造函數(shù)執(zhí)行時,靜態(tài)變量duckCount的值就會增加1
public Duck(){
duckCount ++;
System.out.println("duckCount的值是:"+duckCount);
}
public void setSize(int s){
size = s;
}
public int getSize(){
return size;
}
}
package chap10;
public class TestDuck {
public static void main(String[] args) {
Duck d1 = new Duck();
d1.setSize(10);
System.out.println(d1.getSize());
Duck d2 = new Duck();
d2.setSize(20);
System.out.println(d2.getSize());
Duck d3 = new Duck();
d3.setSize(30);
System.out.println(d3.getSize());
Duck d4 = new Duck();
d4.setSize(40);
System.out.println(d4.getSize());
System.out.println("靜態(tài)變量duckCount的值:"+Duck.duckCount);
}
}
結(jié)果:
duckCount的值是:1
10
duckCount的值是:2
20
duckCount的值是:3
30
duckCount的值是:4
40
靜態(tài)變量duckCount的值:4
靜態(tài)變量的起始動作:類被加載時初始化。
靜態(tài)項目的初始化有兩項保證:
- 靜態(tài)變量會在該類的任何對象創(chuàng)建之前就完成初始化
- 靜態(tài)變量會在該類的任何靜態(tài)方法執(zhí)行之前就初始化
默認(rèn)值:主數(shù)據(jù)類型:0/0.0/false;對象引用:null
如果沒有給靜態(tài)變量賦初值,它會被設(shè)定默認(rèn)值。靜態(tài)變量的默認(rèn)值就是該變量類型的默認(rèn)值。
6、靜態(tài)的final變量是常數(shù)
標(biāo)記為final的變量,一旦被初始化就不會改動;
類加載后,靜態(tài)final變量就一直會維持原值。
舉例:public static final double PI = 3.141592653589793;
- public 可以供各方讀取
- static,不需要Math的實例
- final,類加載后,不變
注意:如何區(qū)分變量為不變的常數(shù):都是大寫字母!
靜態(tài)final變量初始化:
方法一:聲明的時候
public class Foo{
public static final int FOO_X = 25;
}
方法二:在靜態(tài)初始化程序中
public class Foo{
public static final double BAR_SIGN;
// 類加載時執(zhí)行
static{
BAR_SIGN = (double) Math.random();
}
}
如果以上兩種方法都沒有使用,編譯器會報錯,變量沒有被初始化
7、其他的final
非靜態(tài)final變量:不能改變它的值。
final的方法:不能被覆蓋
final的類:不能被繼承
目的:安全
8、Math的常用方法
1)Math.random() 返回0.0~1.0之間的雙精度浮點數(shù)
double r1 = Math.random();
int r2 = (int) (Math.random() * 5);
2)Math.abs() 返回雙精度浮點型參數(shù)的絕對值,有覆蓋版本
int x = Math.abs(-230); //230
double d = Math.abs(240.45); //240.45
3)Math.round() 返回四舍五入之后的整型或長整型
int x = Math.round(-24.8f);//-25
int y = Math.round(24.45f);//24
4)Math.min() 返回參數(shù)中較小的一個
5)Math.max() 返回參數(shù)中較大的一個
9、主數(shù)據(jù)類型的包裝類
包裝類型
給每個基本類型設(shè)計了一個對應(yīng)的類進(jìn)行代表,這樣八個和基本數(shù)據(jù)類型對應(yīng)的類型統(tǒng)稱包裝類(Wrapper Class),位于 java.lang 包。
| 基本數(shù)據(jù)類型 | 包裝類 |
|---|---|
| byte | Byte |
| short | Boolean |
| int | Integer |
| long | Long |
| double | Double |
| float | Float |
| char | Character |
| boolean | Boolean |
除了Integer和Character類,其他類都和基本類型一致,只是類名第一個字母大寫。
為什么要包裝類:
有些地方需要用到對象而不是基本數(shù)據(jù)類型,比如集合的容器要求元素是 Object類型,因此int、double等類型就benign放進(jìn)去。
拆箱和裝箱
裝箱(boxing): 基本數(shù)據(jù)類型 --> 包裝類,實現(xiàn):包裝類.valueof()
拆箱(unboxing):包裝類 --> 基本數(shù)據(jù)類型,實現(xiàn):包裝類對象.xxValue()
舉例:
// 裝箱
Integer integer = Integer.valueof(1);
// 拆箱
int i = integer.intValue();
自動拆箱和自動裝箱
java自動把上述過程實現(xiàn),原理還是:包裝類.valueof() 實現(xiàn)自動裝箱;包裝類對象.xxValue()實現(xiàn)自動拆箱。
public static void main(String[] args){
Integer integer = 1;//裝箱
int i = integer; // 拆箱
}
補(bǔ)充:哪些地方會自動拆裝箱
- 場景1:將基本數(shù)據(jù)類型放入集合類 --》自動裝箱
- 場景2:包裝類型和基本類型的大小比較 --》自動拆箱,== ,包裝類拆箱變成基本數(shù)據(jù)類型比較
- 場景3:包裝類型的計算 --》自動拆箱成基本類型計算
- 場景4:三目運(yùn)算符的使用 --》第2,第3位操作數(shù)分別是基本類型和對象,其中對象會拆箱成基本類型。如果對象是null會發(fā)生空指針異常。
- 場景5:函數(shù)參數(shù)和返回值
10、String 和 primitive主數(shù)據(jù)類型的互轉(zhuǎn)
1)將String轉(zhuǎn)換成primitive 主數(shù)據(jù)類型
package chap10;
public class Test02 {
public static void main(String[] args) {
String s = "2";
// String 轉(zhuǎn)換成int
int x = Integer.parseInt(s);
// String 轉(zhuǎn)換成 double
double y = Double.parseDouble("23.45");
// String 轉(zhuǎn)換成 boolean
// Boolean 的構(gòu)造函數(shù)可以取用String來創(chuàng)建對象
boolean b = new Boolean("true").booleanValue();
}
}
有異常的場景:
String t = "two";
int z = Integer.parseInt(t);
編譯不報錯,運(yùn)行報錯

2)將primitive 主數(shù)據(jù)類型轉(zhuǎn)換成String
// 主數(shù)據(jù)類型轉(zhuǎn)換成String
double d = 42.5;
// 方法1:使用 + 操作符
String doubleString = ""+d;
// 方法2:使用靜態(tài)方法 toString()
String doubleString2 = Double.toString(d);
11、數(shù)字的格式化,格式化解析
將數(shù)字以帶逗號的形式格式化:舉例
public class TestFormats {
public static void main(String[] args) {
// 格式設(shè)定:將數(shù)字以都逗號分開
String s = String.format("%,d",1000000000);
System.out.println(s); // 1,000,000,000
}
}
format("%,d",1000000000) 格式化的兩部分:格式指令 + 要格式化的值。
1)格式指令:"%,d" ,說明:% 符號表示把第二個參數(shù)放到這里;",d" 該參數(shù)要使用的格式
2)要格式化的值:1000000000
含義:把第二個參數(shù)以第一個參數(shù)所表示帶有逗號的整數(shù)方式表示。
常用格式化語句語法:
%,d :代表以十進(jìn)制整數(shù)帶有逗號的方式表示
%.2f :代表以小數(shù)點后兩位的方式格式化此浮點數(shù)
%,.2f :代表整數(shù)部分以有逗號的形式表示,小數(shù)部分保留兩位
“格式化說明的格式”

必填的只有類型,比如 %d、%f、%x、%c。
有多項參數(shù)時:按照順序?qū)?yīng)到格式化設(shè)定
int one = 23456567;
double two = 12345.34567;
String result = String.format("the rank is %,d out of %,.2f",one,two);
System.out.println(result);//the rank is 23,456,567 out of 12,345.35
12、日期
日期的格式化:
Date today = new Date();
String t1 = String.format("%tc", today);// 完整的日期和時間
String t2 = String.format("%tr",today);// 只有時間
String t3 = String.format("%tA %tB %td",today,today,today);// 周、月、日
System.out.println("t1: "+ t1);//t1: 星期一 五月 09 17:46:05 CST 2022
System.out.println("t2: "+ t2);//t2: 05:46:05 下午
System.out.println("t3: "+ t3);//t3: 星期一 五月 09
Java.util.Date
適合取得當(dāng)前時間,如:Data today = new Date();
Java.util.Calendar
1、Calendar 抽象的
抽象類無法new 對象創(chuàng)建實例,但是可以調(diào)用其靜態(tài)方法 getInstance(),會返回繼承過Calendar的對象。
Calendar cal = Calendar.getInstance();
大部分java版本會返回 java.util.GregorianCalendar 的實例。
2、運(yùn)用Calendar對象
- 字段會保存狀態(tài)
- 日期和時間可以運(yùn)算
- 日期和時間可以用微秒表示
package chap10;
import java.util.Calendar;
public class TestCalendar {
public static void main(String[] args) {
Calendar c = Calendar.getInstance();
c.set(2022,3,14,18,30);
System.out.println(c);//java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=19,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2022,MONTH=3,WEEK_OF_YEAR=20,WEEK_OF_MONTH=2,DAY_OF_MONTH=14,DAY_OF_YEAR=129,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=6,HOUR_OF_DAY=18,MINUTE=30,SECOND=0,MILLISECOND=398,ZONE_OFFSET=28800000,DST_OFFSET=0]
// 當(dāng)前時間以微秒展示
long day1 = c.getTimeInMillis();
System.out.println(day1);//1649932200398
// day1 加上一個小時
day1 += 1000*60*60;
System.out.println(day1);//1649935800398
//加一個小時
c.setTimeInMillis(day1);
System.out.println("new hour:"+c.get(c.HOUR_OF_DAY));//new hour:19
// 加35天
c.add(c.DATE,35);
System.out.println("add 35 days: "+c.getTime());// add 35 days: Thu May 19 19:30:48 CST 2022
//滾動35天
c.roll(c.DATE,35);
System.out.println("roll 35 days: "+c.getTime());//roll 35 days: Mon May 23 19:30:48 CST 2022
// 設(shè)置DATE的值
c.set(c.DATE,1);
System.out.println("set to one: "+c.getTime());//set to one: Sun May 01 19:30:26 CST 2022
}
}
浙公網(wǎng)安備 33010602011771號