JavaSE语法之六:类和对象(超全!!!)

2023-12-13 10:42:14

一、面向对象的初步认识

1. 什么是面向对象

Java中一切皆对象!
Java是一门纯面向对象的语言(Object Oriented Program,简称OOP)。一切皆对象,面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事。
– 面试官问你OOP是啥,要知道是面向对象。

2. 面向对象与面向过程

比如:买手机
面向过程:关注买手机的过程

上网查配置 ——> 打开购物平台 ——> 选参数 ——> 选手机 ——> 下单 ——> 填地址 ——> 付款 ——> 取快递 ——> 使用

面向对象:不关注买手机的过程,只关注对象,通过对象之间的交互来完成

①给秘书说要买手机
②秘书帮我买手机:查参数……
③我使用
在 我、秘书、手机 三个实体对象之间相互协作完成。

要是拿到一个对象,必须先类!
类返回对象的过程——实例化

二、类和对象

类: Java中通过 “类” 来描述事物,类主要是由 “属性” 和 “行为” 构成。
如:洗衣机

类:洗衣机
属性:品牌、型号、产品重量、外观尺寸、颜色……
行为:洗衣、烘干、定时……

对象: 某个事物的具体存在

【类和对象的关系】

  • 类:属性和行为的集合,是一个抽象的概念

  • 对象:是该类事物的具体体现,是一种具体存在

  • 举例:

    • 手机(类)
    • 张三的手机(对象)

三、类的定义和使用

【如何定义一个类】
就是把一系列相关事物共同属性和行为抽取出来的过程(抽象)

  1. 类: class为定义类的关键字;
  2. 成员变量: 事物的属性,写在类中,方法外;
  3. 成员方法: 事物的行为,写在类中。
// 创建洗衣机类
class WashMachine{
		//定义成员变量
	public String brand; //品牌
	public String type; // 型号
	public String color; // 颜色

		//定义成员方法
	public void washClothes(){ // 洗衣服
		System.out.println("洗衣功能");
	}
	public void dryClothes(){ // 脱水
		System.out.println("脱水功能");
}
	public void setTime(){ // 定时
		System.out.println("定时功能");
}
}

【注意】

  • 类名注意采用大驼峰定义;
  • 成员变量前写法统一为 public;
  • 成员方法不带static。

四、类的实例化

定义了一个类,就相当于在计算机中定义了一种新的类型。用 “类” 类型创建对象的过程,成为类的实例化。

  1. 用new关键字创建一个对象的实例;
  2. .来访问对象中的属性和方法;
  3. 一个类可以创建多个对象。

如:接上述洗衣机代码

public class Test {
	public static void main(String[] args) {
		WashMachine w1 = new WashMachine(); //类的实例化
        w1.brand = "美的"; //访问属性
        System.out.println(w1.brand); 
        w1.washClothes(); //访问方法
}
}

【输出结果】
在这里插入图片描述

【注意】

  1. 当一个引用,赋值为 null 的时候,代表这个引用不指向任何对象 ,报空指针异常!
		WashMachine w = null;
        w.brand = "haha";
        System.out.println(w.brand); //不指向任何对象,此时会报空指针异常
  1. 引用也不能指向引用,引用要指向对象。
		 WashMachine w1 = new WashMachine();
        WashMachine w2 = new WashMachine();
        w1 = w2; //错误,这个代表w1这个引用 指向了 w2这个引用指向的对象,此时,w1和w2所指向一个地址。
  1. 一个引用也不能指向多个对象
		WashMachine wm1 = new WashMachine();
        wm1 = new WashMachine();
        wm1 = new WashMachine();
        wm1 = new WashMachine(); //最后wm1只是指向了一个对象,就是最后一个

五、this引用

1. 概述
这个. 表示本类对象的引用,本质是一个对象。

2. 特性
每一个普通方法都有一个this,谁调用该方法,this就指向谁。

  1. this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型;
  2. this只能在“成员方法”中使用;
  3. 在“成员方法”中,this只能引用当前对象,不能再引用其他对象;
  4. this是“成员方法”第一个隐藏的参数,编译器会自动传递,再成员方法执行时,编译器会负责将调用成员方法对象的引用传递给该成员方法,this来接收u。

3. 用法
①this访问成员变量(this.data;);

	public void srtDate(int year,int month,int day) {
	//加上this 来表示给当前的对象的属性赋值。
		this.year = year;
		this.month = month;
		this.day = day;
}

②this访问成员方法(this.func());

  public int year;
    public int month;
    public int day;
    this.show(); //访问成员方法
    public void setDate(int year, int month, int day) {
    	this.show(); //访问成员方法
        this.year = year; //为当前对象的year赋值,前面的是当前对象,后面的是局部变量。
        this.month = month;
        this.day = day;
    }

③this访问构造方法(this(…))。

   public int year;
    public int month;
    public int day;

//构造方法
    public DateUtil() {
		//this访问构造方法
        this(1999,9,9);
        System.out.println("不带参数的构造方法!");
    }

    public DateUtil(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }

this不能调用静态的 成员方法 和 属性。

4. 总结
局部变量和成员变量重名(如:age),则 this.age为局部变量。
以后要习惯使用this。

六、对象的构成及初始化

1. 如何初始化对象

我们知道,在Java方法内部定义一个局部变量时,必须要初始化,否则编译失败。

		public static void main(String[] args) {
			int a;
			System.out.println(a);
	}
// Error:(26, 28) java: 可能尚未初始化变量a

如果要让上述代码通过编译,只需给定a一个初始值即可。但如果是对象,

	public static void main(String[] args) {
		Date d = new Date();
		d.printDate();
		d.setDate(2021,6,9);
		d.printDate();
}
// 代码可以正常通过编译

需要调用之前写的setDate方法才能将具体的日期设置到对象中,通过上述例子,我们发现两个问题:
①每次对象创建好后调用setDaye方法设置具体的日期,比较麻烦,那对象该如何初始化?
②局部变量必须要初始化才能使用,为什么字段声明之后没有给值依然可以使用?

2. 构造方法

【概述】
构造方法(也称为构造器)是一个特殊的成员方法,名字必须与类名相同,在创建对象时,由编译器自动调用,并且在整个对象的生命周期内只调用一次。
Dog d = new Dog(); 这里是实例化对象,此时会调用对象的构造方法。

当我们调用完构造方法,对象就生成了!! 生成对象分两步:
①为对象分配内存;
②调用合适的构造方法。

	public class Date {
	//成员变量
		public int year;
		public int month;
		public int day;

	public void setDay(int year, int month, int day){ 
		this.year = year;
		this.month = month;
		this.day = day;
	}
	//成员方法
	public void printDate(){
		System.out.println(this.year + "/" + this.month + "/" + this.day);
	}
	
	//构造方法
	public Date() { 
  		System.out.println("不带参数的构造方法")
	}
	
	public static void main(String[] args) {
		// 构造三个日期类型的对象 d1 d2 d3
		Date d1 = new Date();
		Date d2 = new Date();
		Date d3 = new Date();
		// 对d1,d2,d3的日期设置
		d1.setDay(2020,9,15);
		d2.setDay(2020,9,16);
		d3.setDay(2020,9,17);
		// 打印日期中的内容
		d1.printDate();
		d2.printDate();
		d3.printDate();
	}
}

//此时输出
不带参数的构造方法
2020/9/15
不带参数的构造方法
2020/9/16
不带参数的构造方法
2020/9/17

可以实例化对象给构造方法传参,此时不用调用上述的setDate方法:

	//要手动加入不带参数的构造方法,不管写了啥构造方法,此时Java都不会提供不带参数的构造方法了
	public Date() {}
	public Date(int year, int month, int day){
		this.year = year;
		this.month = month;
		this.day = day;
		System.out.println("带有3个参数的构造方法");
	}
	
	public static void main(String[] args) {
		Date d = new Date(2021,6,9); 
		d.printDate(); 
	}

//输出
带有3个参数的构造方法
2021-6-9

【特性】
①名字必须与类名相同
没有返回值类型,设置void也不行;
③创建对象时由编译器自动调用,并且在对象的生命周期内只调用一次(相当于人的出生,每个人只能出生一次);
④构造方法可以重载(用户根据自己的需求提供不同参数的构造方法)。
⑤如果用户没有显示定义,编译器会生成一份默认的构造方法,生成的默认构造方法一定是无参的;其中注意,一旦用户定义,编译器则不再自动生成默认的构造方法。
⑥构造方法中,可以通过this调用其他构造方法来简化代码。

    public int year;
    public int month;
    public int day;

//构造方法
    public DateUtil() {
        this(1999,9,9);
        System.out.println("不带参数的构造方法!");
    }

    public DateUtil(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }

注意:
上述无参方法中的this(1999,9,9);就是调用当前对象的其他构造方法。此语句 ① 必须放在第一行;② 只能在构造方法内部才能使用。③ 不能成环。(就是不能两个及以上的构造方法使用this(…),这样会在其内部踢皮球了。)

⑦绝大多数情况下使用 public 来修饰,特殊场景下会被private修饰(后续将单例模式时会遇到)。

3. 默认初始化

在上文提出的第二个问题:为什么局部变量在使用时必须要初始化,而成员变量可以不用呢?

在调用构造方法给对象赋值之前,系统内部会自动默认初始化。
在这里插入图片描述
要搞清楚这个过程,就需要知道 new 关键字背后所发生的一些事情:

Date d = new Date(2021,6,9);

在程序层面只是简单的一条语句,在JVM层面需要做好多事情,下面简单介绍下:

  1. 检测对象对应的类是否加载了,如果没有加载则加载;

  2. 为对象分配内存空间;

  3. 处理并发安全问题;
    比如:多个线程同时申请对象,JVM要保证给对象分配的空间不冲突;

  4. 初始化所分配的空间
    即:对象空间被申请好之后,对象中包含的成员已经设置好了初始值,比如:
    在这里插入图片描述

  5. 设置对象头信息(关于对象内存模型后面会介绍);

  6. 调用构造方法,给对象中各个成员赋值。

4. 就地初始化

在声明成员变量时,就直接给出了初始值。

	public class Date {
	  //定义初始值
		public int year = 1900;
		public int month = 1;
		public int day = 1;
		
		public Date(){
	}

注意:代码编译完成后,编译器会将所有给成员初始化的这些语句添加到各个构造函数中

文章来源:https://blog.csdn.net/T2283380276/article/details/134882970
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。