【从零开始的Java开发】1-3-1 Java面向对象:创建类、实例化对象、单一职责原则、new、this、构造方法

面向对象

类和对象
类是模型,确定对象将会拥有的特征(属性)和行为(方法)
对象是类的实例化表现

类是对象的类型
对象是特定类型的数据

属性和方法
属性:对象所具有各种静态特征——对象有什么
方法:对象具有的各种动态行为——对象能做什么

类和对象的关系

  • 抽象的概念
  • 模板

对象

  • 一个看得到、摸得着的具体实体

流程:创建类——实例化对象——完成具体的程序

创建类

在Java中,可以通过包(package)对类(class)进行管理。
包名:

  • 英文小写
  • 域名倒序

一个宠物猫类:

package com.pet;

public class Cat {

	// 属性:昵称、年龄、体重、品质
	String name;
	int age;
	double weight;
	String species;

	// 方法:跑、吃
	// 跑
	public void run() {
		System.out.println("run!");
	}

	// 吃
	public void eat() {
		System.out.println("eat!");
	}

	
}

实例化对象

package com.pet;

public class CatTest {

	public static void main(String[] args) {
		//对象实例化
		Cat one=new Cat();
		
		//测试
		one.eat();
		one.run();
	}

}

输出:

eat!
run!

注意,如果一个变量没有赋值,则它不能被打印输出。
但如果一个对象的属性没有被赋值,可以输出。

public class CatTest {

	public static void main(String[] args) {
		//对象实例化
		Cat one=new Cat();		
		System.out.println(one.age);
		System.out.println(one.name);
	}
}

输出:

0
null

也就是说,对象的属性没有被初始化,但它会有默认值。

我们可以通过=给对象的属性赋值

public class CatTest {

	public static void main(String[] args) {
		//对象实例化
		Cat one=new Cat();	
		System.out.println(one.name);
		one.name="A";		
		System.out.println(one.name);
	}
}

输出:

null
A

单一职责原则/单一功能原则

不要存在多于一个导致类变更的原因
一个类中承担的功能越多,它的交融、耦合性就越高,则它被服用的可能性就降低了。而且,若一个类的耦合性高,且类中的某个职责改变了,则同类的其他职责都要改变。

在程序设计中,我们尽量把不同的能引发变化的原因放进不同的类中,这样一来,当某一方发生变化时,对另一方的影响会小很多。

类间如何识别:
先找同一个类,再找同一个包…这样向上找。

new关键字

对象实例化操作:对象创建。
实例化对象的过程:

  1. 声明对象:Cat one
  2. 实例化对象:new Cat();

流程:

  1. 在栈中声明一个对象。
  2. 在堆中开辟一块空间(new)。
  3. 通过赋值符号,将堆中开辟的空间地址存放到栈的对象中。

声明对象
在内存的区域开辟了一个空间,取名为one:此时one还不是一个有效的对象,因为它是空的。

如:
在这里插入图片描述
错误提示:当前对象没有初始化。

实例化对象
在内存的中开辟了一块空间,完成了这个对象相关信息的鹅初始化操作。

栈 VS 堆
栈:存放局部变量。
堆:存放动态数据。

基本数据类型(栈)和引用数据类型(栈、堆):
基本数据类型:栈中保存的是值,如:int a=10会在栈中开辟一个空间,名为a,存的是10;
引用数据类型:栈中保存的是指向堆中具体空间的地址——可以根据它找到在堆中的实例。

用赋值=符号把声明和实例化关联
把堆空间里新开辟的地址存放到了one当中。相当于把一个新房子的钥匙交到了one的手里,one有了钥匙,就可以去房子里了。

Cat one=new Cat();	

不同的对象会开辟不同的空间,尽管它们的属性值一样,它们也是不同的对象。

其他实例化方式

Cat two=one;

one里存的是堆中开辟的地址,赋值后,one和two指向同一块内存。
如:

public class CatTest {

	public static void main(String[] args) {
		//对象实例化
		Cat one=new Cat();	
		one.age=1;
		Cat two=one;
		System.out.println("one.age:"+one.age);
		System.out.println("two.age:"+two.age);
		two.age=2;
		System.out.println("one.age:"+one.age);
		System.out.println("two.age:"+two.age);
	}

}

输出:

one.age:1
two.age:1
one.age:2
two.age:2

几点注意事项
需要多此访问同一对象时,必须进行声明

多次访问进行声明:

one.age=1;
one.name="A";

单次访问:匿名对象进行方法调用

new Cat().run();

同一作用范围内,不能定义同名对象
可以同时声明多个引用,用逗号分隔

Cat one,two;
Cat three=new Cat(),four=new Cat();

未使用对象会报错
在这里插入图片描述

构造方法

无参构造方法

也成为构造函数构造器

  1. 构造方法与类名相同且没有返回值
  2. 构造方法的语句格式
  3. 只能在对象实例化的时候调用
  4. 当没有指定构造方法时,系统会自动添加无参的构造方法
  5. 当有指定构造方法,无论是有参、无参的构造方法,都不会自动添加无参的构造方法
  6. 一个类中可以有多个构造方法

构造方法的语句格式格式

访问修饰符 构造方法名(可以加参数){
	//初始化代码
}

一个无参的构造方法

public class Cat {

	// 属性:昵称、年龄、体重、品质
	String name;
	int age;
	double weight;
	String species;

	// 一个无参的构造方法
	public Cat() {
		System.out.println("我是无参构造方法");
	}

	// 方法:跑、吃
	// 跑
	public void run() {
		System.out.println("run!");
	}

	// 吃
	public void eat() {
		System.out.println("eat!");
	}
}

调用one.run();,输出:

我是无参构造方法
run!

说明==在对象实例化的时候会自动调用构造方法。 ==

如果写了一个带参的构造方法,再直接实例化:会报错——无参的构造方法没有被定义
因为:
如果没有定义构造方法,系统会自动定义;
如果定义了构造方法,系统不会自动定义,但系统找不到匹配的构造方法,就会报错。
在这里插入图片描述
这里,如果想要实例化,要么带参,要么再写一个无参的构造方法。

public Cat(String name) {
		System.out.println("我是有参构造方法");
	}

带参实例化:

Cat one=new Cat("A");

带参构造方法

代码:

//一个带参构造方法,依次赋值属性
	public Cat(String name,int age,double weight,String species) {
		name=name;
		age=age;
		weight=weight;
		species=species;
	}

出现警告线:
在这里插入图片描述
测试类如下,并运行:

public static void main(String[] args) {
		//对象实例化
		Cat one=new Cat("A",2,100.0,"英短");	
		System.out.println("昵称:"+one.name);
		System.out.println("年龄:"+one.age);
		System.out.println("体重:"+one.weight);
		System.out.println("品种:"+one.species);
	}

输出:

昵称:null
年龄:0
体重:0.0
品种:null

出错了!错误原因是(如上图警告信息):这几个属性并没有起作用

当我们把鼠标放到参数的name中时,构造方法内的两个name都会被选中。

在这里插入图片描述
当我们选中属性中的name时,构造函数内的name无显示:
在这里插入图片描述
也就是说,实际上参数中的name并没有赋值给属性,这就是就近原则
就近原则:优先使用局部变量。 在构造方法中,我们会先找最近的name进行赋值,只有当构造方法中没有name,才会去外面找name。

解决的方法1:属性和参数不要用一样的变量名。

构造函数代码:

//一个带参构造方法,依次赋值属性
	public Cat(String name1,int age1,double weight1,String species1) {
		name=name1;
		age=age1;
		weight=weight1;
		species=species1;
	}

运行测试类后的输出:

昵称:A
年龄:2
体重:100.0
品种:英短

解决的方法2: this关键字。

this关键字

this是当前对象的默认引用,我们可以朴素地理解为:谁调用了这个构造函数,谁就是当前对象。 如代码:

//一个带参构造方法,依次赋值属性
	public Cat(String name,int age,double weight,String species) {
		this.name=name;
		this.age=age;
		this.weight=weight;
		this.species=species;
	}

我们可以通过this关键字显式地告诉编译器:传入的参数name要赋值给当前对象的name属性。
在这里插入图片描述
运行一下测试代码,输出:

昵称:A
年龄:2
体重:100.0
品种:英短

this也可以调用方法,如:这里表示调用run方法时还要调用当前类的eat方法。

public void run() {
		this.eat();//这里不写this也可以
		System.out.println("run!");
	}

调用run(),输出:

eat!
run!

构造方法调用

如果类里有一个和类名相同的普通方法,不会报错(无语法错误),但会有警告——不推荐这样写。
在这里插入图片描述

普通方法不能调用构造方法。

构造方法的调用只能通过构造方法之间来完成。
在构造函数中用this();调用无参构造函数,this()必须放在第一行:

// 一个无参构造方法
	public Cat() {
		System.out.println("我是无参构造方法");
	}

	// 一个带参构造方法,依次赋值属性
	public Cat(String name, int age, double weight, String species) {
		this();// 这样调用
		this.name = name;
		this.age = age;
		this.weight = weight;
		this.species = species;
	}

测试语句:

Cat one = new Cat("A", 2, 100.0, "英短");	

输出:

我是无参构造方法

用无参的构造方法调用有参的构造方法:

// 一个无参构造方法
	public Cat() {
		//用this来调用构造方法要放在第一行
		this("A", 2, 100.0, "英短");
		System.out.println("我是无参构造方法,我要调用有参构造方法");			
	}
	
	
	// 一个带参构造方法
	public Cat(String name, int age, double weight, String species) {			
		this.name = name;
		this.age = age;
		this.weight = weight;
		this.species = species;
	}

测试类:

public static void main(String[] args) {
		// 对象实例化
		Cat one = new Cat();
		System.out.println("昵称:" + one.name);
		System.out.println("年龄:" + one.age);
		System.out.println("体重:" + one.weight);
		System.out.println("品种:" + one.species);
		// one.run();
	}

输出:

我是无参构造方法,我要调用有参构造方法
昵称:A
年龄:2
体重:100.0
品种:英短

总结

关于变量和对象属性的初始化:

  • 如果一个变量没有赋值,则它不能被打印输出
  • 对象的属性没有被初始化时会有默认值

关于声明对象和实例化对象:

  • 声明对象:栈
  • 实例化对象:堆
  • 实例化对象就是把堆空间里新开辟的地址存放到了栈当中

单一职责原则:不要存在多于一个导致类变更的原因。

构造方法:

  1. 构造方法与类名相同且没有返回值
  2. 构造方法的语句格式
  3. 只能在对象实例化的时候调用
  4. 当没有指定构造方法时,系统会自动添加无参的构造方法
  5. 当有指定构造方法,无论是有参、无参的构造方法,都不会自动添加无参的构造方法
  6. 一个类中可以有多个构造方法

如果没有定义构造方法,系统会自动定义;
如果定义了构造方法,系统不会自动定义,但若系统找不到匹配的构造方法,就会报错。

带参构造方法:
两种对属性起作用的语句:

-参数与属性不同名:

name=name1;//属性是name,参数是name1
  • this关键字
this.name=name;
//第一个name是对象的属性name,第二个name是参数
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

karshey

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值