Lesson3 类

0 Java中的数据类型

  • 基本数据类型
    • 数值型
      • 整数类型:byte, short, int, long
      • 浮点类型:float, double
    • 字符型:char
    • 布尔型:boolean
  • 引用数据类型
    • 类:class
    • 接口:interface
    • 数组:[]
类型名称 关键字 占用位数 取值范围
整数 字节型 byte 8 -27~27-1
短整型 short 16 -215~215-1
整型 int 32 -231~231-1
长整型 long 64 -263~263-1
小数 单精度浮点数 float 32 1.4e-45f~3.4028235e+38f
双精度浮点数 double 64 4.9e-324d~1.7976031348523157e+308d
字符型 char 16 0-65535或u0000-\UFFFF
布尔型 boolean 8 true和false

变量的作用域:一对{}之间

1 Java程序的基本结构

  • java源文件的基本语法
    [<包声明>]
    [<导入声明>]
    <类声明>
    
+ 例:
  ```java
  package shipping.reports;
  
  import shipping.domain.*;
  import java.util.List;
  import java.io.*;
  
  public class VehicleCapacityReport{
	  private List vehicles;
	  public void generateReport(Writer output){...}
  }
  • java程序的三大件
    • 包的声明:指定类所在的位置
    • 类的导入:用到其他位置中的类
    • 类的定义:核心部分

2 类的定义

2.1 类的定义

  • 类的定义格式
    Pasted image 20241017210320.png

  • 访问控制符:public或默认(即没有访问控制符)
    public类一般含有main方法

  • 类型说明符:finalabstract

2.2 成员变量的定义

[]表示可有可无

  • 定义格式:[修饰符] 变量的数据类型 变量名[=初始值]
  • 常用的修饰符:thisstaticpublicprivateprotected、默认

2.2.1 this 引用

  • Java每个类都默认地具有 null、this、 super三个域,所以在任何类中都可以不加说明就可以直接引用它们
    • null :代表“空”,用在定义一个对象但尚未为其开辟内存空间时。
    • this 和 super :是常用的指代本类对象和父类对象的关键字
  • this可以看做一个变量,他的值是当前对象的引用
  • 使用this可以处理方法中成员变量和局部变量重名的问题 Pasted image 20241017210339.png

2.3 成员方法的定义

[]表示可有可无

  • 定义格式
    [修饰符] 返回值类型 方法名([形参说明])[thorws 例外名1,例外名2...]{
    局部变量声明;
    执行语句组;
    }
    
  • 常用的修饰符:publicprivateprotectedstaticfinal
  • 返回值:方法一般需要有一个返回值表示执行结果,也可以无返回值(用void表示)。返回值类型可以是Java类型系统中的所有类型。

2.4 创建对象

  • new关键字创建对象
  • 使用对象属性:对象名.成员变量
  • 使用对象方法:对象名.方法名

2.5 基本类型和引用类型作为参数传递

2.5.1 基本类型:深拷贝

class Demo{
    public static void main(String[] args){
        int x = 4;
        show(x);
        System.out.println("x="+x);
    }
    public static void show(int x){
        x = 5;
    }
}

/*
【输出】
x=4
*/
  • 基本类型作为参数传递时,其实就是将基本类型变量x空间中的值复制了一份传递给调用的方法show();
  • 当在show()方法中x接受到了复制的值,再在show()方法中对x变量进行操作,这时只会影响到show中的x;
  • 当show方法执行完成,弹栈后,程序又回到main方法执行,main方法中的x值还是原来的值

2.5.2 引用类型:浅拷贝

class Demo{
	int x ;
	public static void main(String[] args){
		Demo d = new Demo();
        d.x = 5;
        show(d);
        System.out.println("x="+d.x);
    }
    public static void show(Demo d){
        d.x = 6;
    }
}

/*
【输出】
x=6
*/
  • 当引用变量作为参数传递时,这时其实是将引用变量空间中的内存地址(引用)复制了一份传递给了show方法的d引用变量。这时会有两个引用同时指向堆中的同一个对象。当执行show方法中的d.x=6时,会根据d所持有的引用找到堆中的对象,并将其x属性的值改为6。
  • 由于是两个引用指向同一个对象,不管是哪一个引用改变了引用的所指向的对象的中的值,其他引用再次使用都是改变后的值。

2.6 方法的重载

  1. 方法的重载是指一个类中可以定义有相同的名字,但参数不同的多个方法,调用时会根据不同的参数表选择对应的方法。
  2. 重载方法必须满足以下条件:
    • 方法名相同。
    • 方法的参数类型、个数、顺序至少有一项不相同
    • 方法的返回类型可以不相同。
    • 方法的修饰符可以不相同。
  3. 调用重载方法时,Java使用参数的类型和数量决定实际调用重载方法的哪个版本。

3 对象的生成、使用和清除

  • 构造方法有两种,构造方法可以重载,并且通常是重载的,一种是不带参数构造方法(默认构造方法),另一种是带参数构造方法。
  • 构造方法(constructor)是一类特殊的成员方法。
  • Java语言中每个类至少有一个构造方法。
  • 构造方法与类同名没有任何返回值

3.1 默认构造函数

  • 如果类的定义者没有显式的定义任何构造方法,系统将自动提供一个默认的构造方法
    • 默认构造方法没有参数
    • 默认构造方法没有方法
  • 无参构造函数创建对象时,成员变量的值被赋予了数据类型的隐含初值
    Pasted image 20241017210407.png
  • 如果类中没有定义构造函数,编译器会自动创建一个默认的不带参数的构造函数;如果程序员为类定义了构造函数,Java就不会为该类创建默认的不带参数的构造函数。
public class Teacher5 {
    private String name;  // 教员姓名
    // 构造方法
    public Teacher5() {
    	name = "Mary";
    }
}
public class Teacher5Test {
	public static void main(String[ ] args) {
	Teacher5 teacher = new Teacher5();
	}
}

3.2 带参数构造函数

  • 构造函数实例化类对象的格式类名 对象名=new 构造函数(实际参数)
public class Teacher6 {
	private String name;	// 教员姓名
	private int age;		// 年龄   
	private String education;	// 学历
	private String position;	// 职位
	// 带参数的构造方法
	public Teacher6(String pName,int pAge,String pEducation,String pPosition) {
        name = pName;
        age = pAge;    // 可以增加对age等属性的存取限制条件
        education = pEducation;
        position = pPosition;
    }
    public String introduction() {
    	return "大家好!我是" + name + ",我今年" + age + "岁,学历" + education + ",目前职位是"+position;
    }
}

public class Teacher6Test {
	public static void main(String[] args) {
        Teacher6 teacher = new Teacher6("Mary", 23, "本科", "咨询师");
        System.out.println(teacher.introduction());
	}
}

3.3 垃圾内存自动回收机制

  • Java虚拟机后台线程负责内存的回收。
  • 垃圾强制回收机制:Java系统提供了方法System.gc()Runtime.gc()方法来强制立即回收垃圾(但系统并不保证会立即进行垃圾回收)。
  • 判断一个存储单元是否是垃圾的依据是:该存储单元所对应的对象是否仍被程序所用。
  • Java的垃圾收集器自动扫描对象的动态内存区,对所引用的对象加标记,然后把没有引用的对象作为垃圾收集起来并释放出去。
  • Java虚拟机可以自动判断并收集到“垃圾”,但一般不会立即释放它们的存储空间。
  • Java系统自己定义了一套垃圾回收算法,用来提高垃圾回收的效率。
  • Java没有提供析构方法,但提供了一个类似的方法:protected void finalize()。Java虚拟机在回收对象存储单元之前先调用该对象的finalize方法,如果该对象没有定义finalize方法,则java系统先调用 该对象默认的finalize方法。

4 匿名对象

  • 如果对一个对象只需要进行一次方法调用,那么就可以使用匿名对象。

  • 我们经常将匿名对象作为实参传递给一个函数调用

  • 例如:

    Student stu = new Student();//stu是对象,名字是stu
    new Student();//这个也是一个对象,但是没有名字,称为匿名对象
    new Student().show(); //匿名对象方法调用
    

5 关于变量

  • 进一步理解引用类型变量:对象由两部分组成——对象的实体和对象的引用
  • 成员变量vs局部变量
    • 初始化不同:自动初始化只用于成员变量;方法体中的局部变量不能被自动初始化,必须赋值后才能使用。
    • 定义的位置不同:定义在类中的变量是成员变量;定义在方法中或者{}语句里面的变量是局部变量。
    • 在内存中的位置不同:成员变量存储在内存的对象中;局部变量存储在内存的方法中。
    • 声明周期不同:成员变量随着对象的出现而出现在堆中,随着对象的消失而从堆中消失;局部变量随着方法的运行而出现在栈中,随着方法的弹栈而消失。
  • 类的访问机制
    • 在一个类中的访问机制:类中的方法可以直接访问类中的成员变量
    • 在不同类中的访问机制:先创建要访问类的对象,再用对象访问类中定义的成员

6 toString()方法

  • 在java中,所有对象都有默认的toString()这个方法

  • 创建类时没有定义toString()方法,输出对象时会输出对象的哈希码值(对象的内存地址

  • 它通常只是为了方便输出,比如System.out.println(xx),(xx是对象),括号里面的”xx”如果不是String类型的话,就自动调用xx的toString()方法

  • toString()的定义格式

    public String toString(){
    return 字符串;		// 方法体
    }
    

7 类的静态属性和静态方法

7.1 静态属性

  • static修饰的属性(变量)称为静态属性,又叫类变量
  • 即使没有创建该类的具体对象,类中的static类成员也会存在,这时可以通过类名.类变量或者对象名.类变量进行调用
    Pasted image 20240930161708.png
    Pasted image 20240930161717.png

7.2 静态方法

  • static修饰的方法称为静态方法,又叫类方法(静态方法里,无this);
  • 即使没有创建该类的具体对象,类中的static类成员也会存在,这时可以通过类名.类方法或者对象名.类方法进行调用
  • 静态方法与非静态方法的区别
    • 静态方法是在类中使用staitc修饰的方法,在类定义的时候已经被装载和分配(早加载)。而非静态方法是不加static关键字的方法,在类定义时没有占用内存,只有在类被实例化成对象时,对象调用该方法才被分配内存(晚加载)
    • 静态方法中只能直接调用静态成员或者方法,不能直接调用非静态方法或者非静态成员(非静态方法要被实例化才能被静态方法调用),而非静态方法既可以调用静态成员或者方法又可以调用其他的非静态成员或者方法。
class Test{
	public int sum(int a, int b){    // 非静态方法
		return a+b;
	}
	public static void main(String[] args){
		int result = (sum1, 2);    // 静态方法调用非静态方法,报错
		System.out.println("result="+result);
	}
}

7.3 静态代码块

  • 静态代码块与非静态代码块的异同点
public class PuTong{
	public PuTong(){
		System.out.println("默认构造方法!-->");
	}
	// 非静态代码块
	{
		System.out.println("非静态代码块!-->");
	}
	// 静态代码块
	static{
		System.out.println("静态代码块!-->");
	}
	// 静态成员方法
	public static void test(){
		System.out.println("普通方法中的代码块!-->");
	}
	public static void main(String[] args){
		PuTong c1 = new PuTong();
		c1.test();
		PuTong c2 = new PuTong();
		c2.test();
	}
}

/*
【输出】
静态代码块!-->
非静态代码块!-->
默认够构造方法!-->
普通方法中的代码块!-->
非静态代码块!-->
默认够构造方法!-->
普通方法中的代码块!-->
*/
  • 相同点:

    • 都是在JVM加载类时且在构造方法执行之前执行,在类中都可以定义多个。
    • 一般在代码块中对一些static变量进行赋值。
  • 不同点:

    • 静态代码块在非静态代码块之前执行:静态代码块—>非静态代码块—>构造方法
    • 静态代码块只在第一次new执行一次,之后不再执行,而非静态代码块在每new一次就 执行一次
  • 静态代码块

    • 静态代码块只能定义在类里面,它独立于任何方法,不能定义在方法里面。
    • 静态代码块里面声明的变量都是局部变量,只在本块内有效。
    • 静态代码块会在类被加载时自动执行,而无论加载者是JVM还是其他的类。
    • 一个类中允许定义多个静态代码块,执行的顺序根据定义的顺序进行。
    • 静态代码块只能访问类的静态成员,而不允许访问实例成员。
Built with MDFriday ❤️