Head First Java学习:第十章-数字很重要

 1、Math 方法:最接近全局的方法

一种方法的行为不依靠实例变量值,方法对参数执行操作,但是操作不受实例变量状态影响,那么为了执行该方法去堆上建立对象实例比较浪费。

举例:

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);

 

总结:在Math这个类中的所有方法都不需要实例变量值。因为这些方法都是静态的,所以无需Math的实例,你会用到的只有类本身。

 

2、非静态方法与静态方法的差别

当 需要方法而不需要类的实例,那么可以用 static 关键字标记出该。

使用 static 关键字标记“不需要类实例的方法”,称为“静态方法”。

举例:

public static int min(int a,int b){

    //返回a与b中较小的值

}

 

如何调用:

  • 以类的名称调用静态方法:min(88,43);
  • 以引用变量的名称调用非静态的方法:

Song t = new Song();

t.play();

 

3、带有静态方法(static)的含义

抽象类(abstract修饰),不能创建出实例,即抽象的类不能被初始化。

 

非抽象的类如何限制初始化?

把构造方法标记为私有(private,只能被同一类的程序调用),则无法创建出类的实例,编译器会知道不能存取这些私有的构造函数。

 

不代表有一个或多个静态方法的类不能被初始化,只要有main的类都有静态方法。main()一般用来启动或测试其他类,从main() 中创建类的实例并调用新实例上的方法。

 

在类中可以组合静态方法和非静态方法。非静态方法都需要以某种实例操作,取得新对象的方法只有通过new或者序列化(deserialization)或者Java Reflection Api。

 

4、静态方法调用其他方法和变量

第一:静态方法不能调用非静态的变量

静态方法使用通过类的名称来调用,不需要类的实例(不知道堆上有哪些实例),所以也无法引用到该类的任何实例变量,也不会知道可以使用哪个实例变量值。

如果调用非静态的变量,会报错:non-static variable size cannot be referenced from a static context

 

第二:静态方法不能调用非静态的方法

非静态方法都是以实例变量的状态来影响该方法的行为。调用非静态方法,会在非静态方法中用到实例变量,但是静态方法无法引用该类的任何实例变量。

如果调用非静态的方法,会报错:non-static method getSize() cannot be referenced from a static context

 

5、静态变量

静态变量是共享的。

同一个类所有的实例共享一份静态变量。

 

实例变量:每个实例一个

静态变量:每个类一个,也叫类变量。类名.静态变量名 存取

 

代码举例:

package chap10;

public class Duck {
    private int size;
    // 静态变量只有在类第一次载入的时候被初始化
    static int duckCount = 0;

    // 构造函数执行时,静态变量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("静态变量duckCount的值:"+Duck.duckCount);

    }
}

结果:

duckCount的值是:1

10

duckCount的值是:2

20

duckCount的值是:3

30

duckCount的值是:4

40

静态变量duckCount的值:4

 

静态变量的起始动作:类被加载时初始化。

静态项目的初始化有两项保证:

  • 静态变量会在该类的任何对象创建之前就完成初始化
  • 静态变量会在该类的任何静态方法执行之前就初始化

 

默认值:主数据类型:0/0.0/false;对象引用:null

如果没有给静态变量赋初值,它会被设定默认值。静态变量的默认值就是该变量类型的默认值。

 

6、静态的final变量是常数

标记为final的变量,一旦被初始化就不会改动;

类加载后,静态final变量就一直会维持原值。

 

举例:public static final double PI = 3.141592653589793;

  • public 可以供各方读取
  • static,不需要Math的实例
  • final,类加载后,不变

注意:如何区分变量为不变的常数:都是大写字母!

 

静态final变量初始化:

方法一:声明的时候

public class Foo{
    public static final int FOO_X = 25;
}

 

方法二:在静态初始化程序中

public class Foo{

public static final double BAR_SIGN;

// 类加载时执行

static{

    BAR_SIGN = (double) Math.random();

}

}

如果以上两种方法都没有使用,编译器会报错,变量没有被初始化

 

7、其他的final

非静态final变量:不能改变它的值。

final的方法:不能被覆盖

final的类:不能被继承

目的:安全

 

8、Math的常用方法

1)Math.random()  返回0.0~1.0之间的双精度浮点数

double r1 = Math.random();

int r2 = (int) (Math.random() * 5);

2)Math.abs() 返回双精度浮点型参数的绝对值,有覆盖版本

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() 返回参数中较小的一个

5)Math.max() 返回参数中较大的一个

 

9、主数据类型的包装类

包装类型

给每个基本类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类型统称包装类(Wrapper Class),位于 java.lang 包。

基本数据类型 包装类
byte Byte
short Boolean
int Integer
long Long
double Double
float Float
char Character
boolean Boolean

除了Integer和Character类,其他类都和基本类型一致,只是类名第一个字母大写。

 

为什么要包装类:
有些地方需要用到对象而不是基本数据类型,比如集合的容器要求元素是 Object类型,因此int、double等类型就benign放进去。

 

拆箱和装箱

装箱(boxing): 基本数据类型 --> 包装类,实现:包装类.valueof()
拆箱(unboxing):包装类 --> 基本数据类型,实现:包装类对象.xxValue()
举例:

// 装箱
Integer integer = Integer.valueof(1);

// 拆箱
int i = integer.intValue();

 

自动拆箱和自动装箱

java自动把上述过程实现,原理还是:包装类.valueof() 实现自动装箱;包装类对象.xxValue()实现自动拆箱。

public static void main(String[] args){
    Integer integer = 1;//装箱
    int i = integer; // 拆箱
}

补充:哪些地方会自动拆装箱

  1. 场景1:将基本数据类型放入集合类 --》自动装箱
  2. 场景2:包装类型和基本类型的大小比较 --》自动拆箱,== ,包装类拆箱变成基本数据类型比较
  3. 场景3:包装类型的计算 --》自动拆箱成基本类型计算
  4. 场景4:三目运算符的使用 --》第2,第3位操作数分别是基本类型和对象,其中对象会拆箱成基本类型。如果对象是null会发生空指针异常。
  5. 场景5:函数参数和返回值

 

10、String 和 primitive主数据类型的互转

1)将String转换成primitive 主数据类型

package chap10;

public class Test02 {
    public static void main(String[] args) {
        String s = "2";
        // String 转换成int
        int x = Integer.parseInt(s);
        // String 转换成 double
        double y = Double.parseDouble("23.45");
        // String 转换成 boolean
        // Boolean 的构造函数可以取用String来创建对象
        boolean b = new Boolean("true").booleanValue();
    }
}

有异常的场景:

String t = "two";
int z = Integer.parseInt(t);

编译不报错,运行报错

 

2)将primitive 主数据类型转换成String

// 主数据类型转换成String
double d = 42.5;
// 方法1:使用 + 操作符
String doubleString = ""+d;
// 方法2:使用静态方法 toString()
String doubleString2 = Double.toString(d);

 

11、数字的格式化,格式化解析

将数字以带逗号的形式格式化:举例

public class TestFormats {
    public static void main(String[] args) {
        // 格式设定:将数字以都逗号分开
        String s = String.format("%,d",1000000000);
        System.out.println(s); // 1,000,000,000
    }
}

 

format("%,d",1000000000) 格式化的两部分:格式指令 + 要格式化的值。

1)格式指令:"%,d"  ,说明:% 符号表示把第二个参数放到这里;",d" 该参数要使用的格式

2)要格式化的值:1000000000

含义:把第二个参数以第一个参数所表示带有逗号的整数方式表示。

 

常用格式化语句语法:

%,d :代表以十进制整数带有逗号的方式表示

%.2f :代表以小数点后两位的方式格式化此浮点数

%,.2f :代表整数部分以有逗号的形式表示,小数部分保留两位

 

“格式化说明的格式”

必填的只有类型,比如 %d、%f、%x、%c。

 

有多项参数时:按照顺序对应到格式化设定

        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 

适合取得当前时间,如:Data today = new Date();

 

Java.util.Calendar 

1、Calendar 抽象的

抽象类无法new 对象创建实例,但是可以调用其静态方法 getInstance(),会返回继承过Calendar的对象。

Calendar cal = Calendar.getInstance();

大部分java版本会返回 java.util.GregorianCalendar 的实例。

 

2、运用Calendar对象

  • 字段会保存状态
  • 日期和时间可以运算
  • 日期和时间可以用微秒表示
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]

        // 当前时间以微秒展示
        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

        // 设置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
    }
}

 

posted @ 2022-05-09 16:12  hqq的进阶日记  阅读(38)  评论(0编辑  收藏  举报