三、类和对象讲解

🚀 一、面对对象的初步认知

🌟 1.1 什么是面向对象?

Java 是一门纯面向对象的语言(Object Oriented Program,继承OOP),在面向对象的世界里,一切皆为对象,面向对象是解决问题的一种思想,主要依靠对象之间的交互完成一件事。

🚀 二、类的定义和使用

面向对象程序设计关注的是对象,而对象相当于生活中的实体。

🌟 2.1 认识简单类

类是用来对一个实体(对象)来进行描述的, 主要描述该对象的属性和功能,描述完成之后计算机可以识别。

🌟 2.2 类的定义格式

JAVA中定义类需要用到 class 关键字

// 创建类
class ClassName{
	field;		// 属性(字段)或成员变量
	method();	// 成员方法
}

❗ 注意事项:
class为定义类的关键字,ClassName 是类名,{} 中的内容是类的主体。

成员变量分为普通成员变量静态成员变量
成员方法也分为普通成员方法静态成员方法

class Person{
	String name;
	int age;
}

采用 Java 语言在计算机中定义类,经 javac 编译之后形成 .class 文件,在JVM 的基础上计算机就可以识别了。

❗ 注意事项:

  1. 类名采用大驼峰定义。
  2. 成员前修饰词统一为 public ,后面详细解释。

🌟 2.3 练习

定义一个学生类:

class Student{
	public String name;
	public String gender;
	public int age;
	public double score;
	
	public void DoClass(){
		;
	}
	public void DoHomework(){
		;
	}
	public void Exam(){
		;
	}

}

注意事项:

  1. 一般一个文件中只会定义一个类。
  2. main 方法所在的类一般使用 public 修饰。
  3. public 修饰的类必须和文件名相同。
  4. 不轻易修改 public 修饰的类的名称。

🚀 三、类的实例化

🌟 3.1 什么是实例化?

定义了一个类,相当于在计算机中新定义了一种数据类型,与 int ,double 类似,新自定义类型
用类类型创建对象的过程,称为类的实例化。使用 new 关键字,配合类名实例化对象

// 定义一个 狗 类
class PetDog{
	// 狗的属性(成员变量)
	public String name;
	public String color;

	// 狗的行为(成员方法)
	public void barks(){
		System.out.println("汪汪汪~~");
	}
	public void wag(){
		System.out.println("摇尾巴");
	}
}

public class Main{
	public static void main(String[] args) {
		PetDog dogh = new PetDog();		// 通过 new 实例化对象
		
		// 普通成员变量的访问要通过对象的引用:dogh.变量或方法
		dogh.name = "大黄";
		dogh.color = "黄";
		
		dogh.barks();
		dogh.wag();
	}
}

那么,接下来有个问题:实例化的对象在内存中是怎样保存的呢?
看下图:
在这里插入图片描述
⛅我们可以知道:
dogh 是一个变量,里面存的是地址,这样的变量也叫做引用。

两种特殊写法

// 1
PetDog d1 = null;
// d1 引用不指向任何对象

// 2
PetDog d2 = dogh;
// d2 引用指向 dogh 引用指向的对象 

❗ 注意事项:

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

🌟 3.2 类和对象的说明

  1. 类只是一个模型,用来对一个实体进行描述。
  2. 类是一种自定义类型,可以用来定义变量。
  3. 一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员
  4. 类就像一个设计图,类实例化出的对象就像根据设计图建造出的房子。

🚀 四、this 引用

🌟 4.1 为什么要有 this 引用

看下面的例子:

class PetDog{
	// 狗的属性(成员变量)
	public String name;
	public String color;
	
	// 类的构造方法,后面会详细讲
	public void SetDog(String name,String color){
		name = name;
		color = color
	}
}

上面 SetDog 方法作用是将传过来的形参 name 和 color 赋值给实例化的类但是:
形参名和成员变量名相同了,无法分清是谁给谁赋值。
要解决这个问题就要用上 this 引用。

🌟 4.2 什么是 this 引用?

this 引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都通过该引用取访问。

class PetDog{
	// 狗的属性(成员变量)
	public String name;
	public String color;
	
	// 类的构造方法,后面会详细讲
	public void SetDog(String name,String color){
		// 通过 this 来引用
		this.name = name;
		this.color = color
	}
}

this 引用的是调用成员方法的对象。
this 引用的三种用法:

  1. this. data 访问类本身成员变量
  2. this. func( ) 访问类本身成员方法
  3. this( ) 调用类本身无参构造方法

🌟 4.3 this 引用的特性

❗ 注意事项:

  1. this 本身无类型,对类的类型引用,哪个对象调用就是哪个对象的类型。
  2. this 只能在 “成员方法” 中使用
  3. 在 “成员方法中”,this 只能引用当前对象,不能再引用其它对象。

🚀 五、对象的构造和初始化

🌟 5.1 如何初始化对象

前面的学习我们知道,JAVA 方法内部定义一个局部变量时,必须初始化,否则会编译失败。

public static void main(String[] args) {
	int a;
	System.out.println(a);
}
// 编译错误,未初始化变量 a

对象的初始化:

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

public static void main(String[] args) {
	Date d = new Date();
	d.printDate();
	d.setDate(2021,6,9);	// 显式初始化
	d.printDate();
}

// 代码可以正常通过编译

通过上面例子可以发现两个问题:

  1. 每次创建好对象都要 调用 SetDate 才能赋值,比较麻烦。
  2. 局部变量必须初始化后才能够使用,为什么上面声明后没有给值仍然可以使用?

🌟 5.2 构造方法

5.2.1 概念

构造方法是特殊的成员方法,名字必须与类名相同,创建对象时,编译器自动调用,并且在整个对象生命周期内只调用一次。

public class Date{
	public int year;
	public int month;
	public int day;
	
	/*	构造方法:
	*	名字与类名相同,没有返回值修饰,设置为 void 也不行	
	*	一般情况下用 public 修饰
	*	创建对象时编译器自动调用,且在对象生命周期内只调用一次。
	*/
	public Date(int year,int month,int day){
		this.year = year;
		this.month = month;
		this.day = day;
		System.out.println("三个参数的构造方法被调用了");
	}
	
	public static void main(String[] args) {
		// 创建一个Date类型的对象,没有显式调用构造方法。
		Date d = new Date(2021,6,9);	// 输出"三个参数的构造方法被调用了"
	}
}

构造方法作用只是对对象中的成员初始化,并不负责给对象开辟空间。

5.2.2 特性

  1. 名字必须与类名相同。
  2. 没有返回值。
  3. 创建对象时编译器自动调用,且在对象生命周期内只调用一次。
  4. 构造方法可以重载(用户根据需求提供不同参数的构造方法)。
public class Date{
	public int year;
	public int month;
	public int day;
	
	// 无参构造方法
	public Date(){
		year = 1990;
		month = 12;
		day = 28;
	}
	
	// 三个参数构造方法
	public Date(int year,int month,int day){
		this.year = year;
		this.month = month;
		this.day = day;
		System.out.println("三个参数的构造方法被调用了");
	}
}
  1. 如果用户没有显式定义,编译器会生成一份默认无参构造方法。但是一旦用户定义了其它构造方法,编译器就不会生成无参构造方法。这也就是为什么对象未初始化也可以编译成功
  2. 构造方法中,可以 this 调用其它构造方法简化代码。
public class Date{
	public int year;
	public int month;
	public int day;
	
	// 无参构造方法
	// 在无参构造方法中通过 this 调用三个参数的构造方法
	// 
	public Date(){
		this(1900,12,28);	// 必须是构造方法中第一条语句
	}
	
	// 三个参数构造方法
	public Date(int year,int month,int day){
		// this();	不可以在这里同时调用无参构造方法,否则会形成环。
		this.year = year;
		this.month = month;
		this.day = day;
		System.out.println("三个参数的构造方法被调用了");
	}
}

⛅注意 :

  • this(…) 必须是构造方法中第一条语句。
  • 不能形成环
  1. 绝大多数情况下,使用 public 修饰,特殊场景下会被 private 修饰。

🌟 5.3 默认初始化

对于上面第二个问题,为什么局部变量在使用时必须要初始化,而成员变量即使不初始化也可以使用呢?

public class Date{
	public int year;
	public int month;
	public int day;

	public static void main(String[] args) {
		Date d = new Date();
		// 成员变量没有初始化也可以使用
		System.out.println(d.year);
		
		// 这里 a 没有初始化,编译报错
		//int a;
		//System.out.println(a);
	}
}

要搞清楚这个过程,就要知道 new 关键字背后发生的一些事情:

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

这条简单语句在 JVM 层面要做好多事情:

  1. 检测对象类是否被加载了,如果没有则加载。
  2. 为对象分配内存空间。
  3. 处理并发安全问题
    比如:多个线程同时申请对象,JVM 要保证给对象分配的空间不冲突。
  4. 初始化所分配的空间
    对象空间被申请之后,对象的成员已经有了初始值
    引用变量的初始值为null
  5. 设置对象头信息,
  6. 调用构造方法,给对象各个成员赋值。

🌟 5.4 就地初始化

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

public class Date{
	public int year = 1900;
	public int month = 1;
	public int day = 1;
}
// 代码编译完成后,编译器会将所有给成员初始化的这些语句添加到各个构造函数中。

🚀 六、封装

🌟 6.1 封装的概念

面向对象的三大特性:封装、继承、多态。,在类和对象阶段,主要研究的就是封装特性,何为封装呢?简单来说就是套壳屏蔽细节
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。

🌟 6.2 访问限定符

JAVA 中主要通过类和访问权限来实现封装:类可以将数据以及封装数据的方法结合在一起,更符合对事物的认知,而访问权限用来控制方法或者字段能否直接在类外使用。
在这里插入图片描述
⛅说明:

  1. protected 主要用在继承中。
  2. default 是是什么都不写时的默认权限。
  3. 访问权限除了可以控制类中的成员的可见性,还可控制类的可见性。
  4. 一般情况下成员变量设置为 private ,成员方法设置为 public。
  5. 不必要公开的数据成员或方法,用 private,具有安全性。
public class test1 {
    public static void main(String[] args) {
        Person person = new Person();
        person.age = 18;
        person.sex = 1;
        person.setName("dsad");
        System.out.println(person.getName()); // // private 修饰变量只能在当前类中使用,这里使用方法调用
    }
}

class Person{
    int age;
    private String name;     // private 修饰变量只能在当前类中使用 ,被封装了
    // 之后可以使用setname() 和 getName() 方法修改和调用 name 的值,这样可以让 private 变量更加安全。
    int sex;

    public  void setName(String name){
        // this 意思是当前对象的引用
        this.name = name;
    }

    public String getName(){
        return this.name;
    }


//    // 编译器可以自动生成 set 和 get方法
//    // Generate --> getter and setter
//
//    public int getAge() {
//        return age;
//    }
//
//    public void setAge(int age) {
//        this.age = age;
//    }
//
//    public int getSex() {
//        return sex;
//    }
//
//    public void setSex(int sex) {
//        this.sex = sex;
//    }
}

🚀 七、static 成员

🌟 7.1 static 修饰成员变量

在JAVA 中,被 static 修饰的成员,成为静态成员,也可称为类成员,静态成员不属于某个具体的对象,是所有对象共享的。

⛅静态成员变量特性:

  1. 不属于某个对象,是类的属性,所有对象共享,不存储在某个对象的空间中。
  2. 可以通过对象或类名访问,但是推荐通过类名访问。
  3. 类静态成员存储在方法区内。
  4. 生命周期是类的生命周期。
public class Student{
	public String name;
	public String gender;
	public int age;
	
	// 静态成员变量
	public static String Room = "1128";
	
	public static void main(String[] args){
		// 静态成员变量可以通过类名直接访问。
		System.out.println(Student.Room);
		
		// 也可以通过对象访问。是所有对象共享的
		Student s1 = new Student();
		Student s2 = new Student();
		
		System.out.println(s1.Room);		
		System.out.println(s2.Room);
	} 
}

❗ 注意:

在普通方法中无法定义静态变量,否则会发生冲突。因为 static 定义的变量属于类变量,其不依赖于对象而存在,但是普通方法必须依赖于对象存在。

🌟 7.2 static 修饰成员方法

Java 中,被 static 修饰的成员方法称为静态成员方法,是类的方法,不是某个对象特有的。静态成员一般是通过静态方法来访问的。

class Student{
	
	// ...
	
	// 静态成员变量
	private static String Room = "1128";
	
	// 返回静态成员变量的静态成员方法
	public static String getClassName(){
		return this.Room;
	}	
}

public class TextStudent{
	public static void main(String[] args){
		// 调用静态成员方法访问 private 静态成员变量
		System.out.println(Student.getClassName());
	}
}

⛅静态成员变量特性:

  1. 不属于某个具体的对象,是类的方法。
  2. 建议直接通过 类名.静态方法名的方式调用。
  3. 不能在静态成员方法中访问任何非静态成员变量。
  4. 普通方法中可以调用静态方法,但是反过来不可以。因为静态方法不依赖对象,而普通方法依赖于对象而存在。

🌟 7.3 static 成员变量初始化

静态成员变量一般不会放在构造方法中初始化,构造方法中初始化的是与对象相关的实例属性。
静态成员变量的初始化分为两种:就地初始化 和 静态代码块初始化。

  1. 就地初始化
public class Stucent{
	// 定义时直接给出初始值
	private static int a = 10;	// 就地初始化
}
  1. 静态代码块初始化

要了解这块知识我们首先要知道代码块的概念。

🚀 八、代码块

🌟 8.1 代码块的概念及分类

**使用{} 定义的一段代码称为代码块。**根据代码块定义的位置和关键字,分为以下四类:

  • 普通代码块
  • 构造代码块
  • 静态代码块
  • 同步代码块(后面多线程部分讲解)

🌟 8.2 普通代码块

定义在方法中的代码块

public class Main{
	public static void main(String[] args){
		{// 直接使用 {} 定义,
			int x = 10;
		}
		int b = 100;
	}
}

这种用法较少见

🌟 8.3 构造代码块

定义在类中的代码块(不加修饰的),也叫实例代码块。
构造代码块一般用来初始化实例成员变量

public class Student{
	private String name;
	private int age;
	
	// 实例代码块
	{
		this.name = "hello";
		this.age = 18;
	}
}

🌟 8.4 静态代码块

使用 static 修饰的代码块称为静态代码块
一般来初始化静态成员变量

public class Student{
	private String name;
	private int age;
	private String gender;
	private static String ClassRoom;

	// 实例代码块
	{
		this.name = "hello";
		this.age = 18;
		this.gender = "man";
	}
	
	// 静态代码块
	static{
		ClassRoom = "1128";
	}
}

❗ 注意事项:

  1. 不管生成多少对象,这个类里的静态代码块都只会执行一次。
  2. 静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的。
  3. 如果一个类中包含多个静态代码块,编译代码时,编译器按照定义的顺序先后运行。
  4. 实例代码块只有创建对象时才会执行。静态代码块全部运行完毕后才会执行其他代码。
class A{
    static{
        System.out.println("A的静态代码块被执行了");
    }
    
    {
        System.out.println("A的实例代码块被执行了");
    }
    
    public A(){
        System.out.println("A的构造方法被执行了");
    }
}

class B extends A{
    static{
        System.out.println("B的静态代码块被执行了");
    }
    
    {
        System.out.println("B的实例代码块被执行了");
    }
    
    public B(){
        System.out.println("B的构造方法被执行了");
    }
}
public class t3 {
    public static void main(String[] args) {
        B b = new B();
    }
}

/*	输出:
	A的静态代码块被执行了
	B的静态代码块被执行了
	A的实例代码块被执行了
	A的构造方法被执行了
	B的实例代码块被执行了
	B的构造方法被执行了
/
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值