面向对象_day01
学习目标:
1. 面向过程与面向对象编程思想
2. 类的定义与对象的创建
3. 匿名对象
4. 类的成员详细讲解
视频教程:https://www.bilibili.com/video/BV1RF411N7LU?spm_id_from=333.999.0.0
一、面向过程与面向对象
面向过程与面向对象是两种编程思想;什么是编程思想呢?编程思想就是编程的思维方式;面向过程的编程思维方式与面向对象的思维方式是截然不同的。
面向过程,强调的是功能行为,以函数为最小单位,考虑怎么做。面向对象,将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。
例如:解决吃饭问题,面向过程与面向对象实现思路如下:
-
面向过程:考虑买什么菜,做什么饭,怎么做,做多少,然后吃饭,洗碗;重心在于如何完成这件事。
-
面向对象:考虑谁会做饭,找到这个人;去饭店吃饭;重心在于调用谁完成这件事。
例如:解决洗衣服问题,面向过程与面向对象实现思路如下:
-
面向过程:考虑用什么洗,凉水洗还是热水洗,洗完是甩干,还是晾晒;重心在于如何完成这件事。
-
面向对象:考虑谁会洗衣服,找到这个人完成这件事;去干洗店洗衣服;重心在于调用谁完成这件事。
例如:解决出行问题,面向过程与面向对象实现思路如下:
-
面向过程:考虑是开车还是步行还是骑行,考虑最佳路线,是否堵车;重心在于如何完成这件事。
-
面向对象:告诉助理,我要去哪里,我要几点去,几点到,剩下的交给助理去做;重心在于调用谁完成这件事。
二、类与对象
上面讲了,面向对象,将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。
那么什么是类?什么是对象呢?
2.1 类与对象的关系
类是指一类事物的抽取,一类事物的概括。比如:人是一类事物。动物是一类事物。宠物狗是一类事物。对象:具体的实例。比如小红是对象。北京动物园的那只老虎。楼上的那条京巴。 类与对象的关系:类是一类事物的总结概括,对象是该类中具体实例,个体。
类(Class)和对象(Object)是面向对象的核心概念。
-
类是对一类事物的描述,是抽象的、概念上的定义
-
对象是实际存在的该类事物的每个个体,因而也称为实例(instance)。
可以理解为: 类 类 = 抽象概念的人;象 对象 = 实实在在的某个人、悟空、八戒、沙僧
面向对象程序设计的重点是 类的设计
2.2 类的设计与对象的创建
类的设计, 其实就是类的成员的设计
2.2.1 类的成员
类是指一类事物的抽取,我们拿人这个类举例,我们可以抽取出人的体重 身高,性别等属性,还可以抽取出学习、吃饭、睡觉等行为。所以抽取类中的成员可以抽取出类的属性和行为。
定义类的格式如下
Java中用类class来描述事物也是如此。常见的类的成员有
- 属 性:对应类中的成员变量
- 行 为:对应类中的成员方法
定义类的具体语法:
其中:属性又叫成员变量,也叫字段,定义的方式和定义变量的方式一样,只是位置不同。
定义方法的语法:
其中 :
- 修饰符:public, 缺省,private, protected等等
- 返回值类型:
- 没有返回值:void
- 有返回值,声明出返回值的类型。与方法体中“ “return ” 返回值” 搭配使用。返回值类型可以是基本类型和引用类型。
- 方法名 :属于标识符,命名时遵循标识符命名规则和规范,“ 见名知意”
- 形参列表:可以包含零个,一个或多个 参数。多个参数时,中间用“, ”隔开
- 返回值:方法在执行完毕后返还给调用它的程序的数据
示例1:定义一个Person类,该类的字段有:name、sex、height、weight;行为有:study、eat、sleep方法。
参考答案:
/**
* 定义一个Person类,该类的字段有:name、sex、height、weight;行为有:study、eat、sleep方法。
*/
public class Person {
//定义成员变量/字段/属性
//姓名
String name;
//性别 0 代表男,1代表女
int sex;
//身高
int height;
//体重
int weight;
//定义方法
//定义学习方法
void study(){
System.out.println("胖叔讲Java,一路相伴");
}
// 定义吃饭方法
void eat(){
System.out.println("吃的是北京烤鸭");
}
// 定义睡觉方法
void sleep(){
System.out.println("早睡早起身体好");
}
}
2.2.2 对象的创建与使用
对象是类的具体实现实例;所以使用类必须根据类创建对象,然后调用对象的属性和方法。
创建对象的语法:
调用属性和方法的语法:
示例1:根据上边定义的Person类创建对象,调用属性和方法
/**
* 定义一个Person类,该类的字段有:name、sex、height、weight;行为有:study、eat、sleep方法。
*/
public class Person {
//定义成员变量/字段/属性
//姓名
String name;
//性别 0 代表男,1代表女
int sex;
//身高
int height;
//体重
int weight;
//定义方法
//定义学习方法
void study(){
System.out.println("胖叔讲Java,一路相伴");
}
// 定义吃饭方法
void eat(){
System.out.println("吃的是北京烤鸭");
}
// 定义睡觉方法
void sleep(){
System.out.println("早睡早起身体好");
}
/*程序入口*/
public static void main(String[] args) {
//定义person对象
Person person = new Person();
//给属性赋值(调用属性)
person.name="胖叔讲java";
person.sex=0;
person.height=168;
person.weight=185;
//查看属性(调用属性)
System.out.println(person.name);
System.out.println(person.sex);
System.out.println(person.height);
System.out.println(person.weight);
//调用方法
person.study();
person.eat();
person.sleep();
}
}
问题分析?上面的学习方法存在问题,到底收获了哪些知识,没有返回结果;吃饭方法也存在问题,不可能天天吃烤鸭,方法体代码写死了,代码不灵活;接下来我们优化代码
参考答案:
/**
* 定义一个Person类,该类的字段有:name、sex、height、weight;行为有:study、eat、sleep方法。
*/
public class Person {
//定义成员变量/字段/属性
//姓名
String name;
//性别 0 代表男,1代表女
int sex;
//身高
int height;
//体重
int weight;
//定义方法
//定义学习方法
String study(){
System.out.println("胖叔讲Java,一路相伴");
return "类与对象";
}
// 定义吃饭方法
void eat(String food){
System.out.println("吃的是:"+food);
}
// 定义睡觉方法
void sleep(){
System.out.println("早睡早起身体好");
}
/*程序入口*/
public static void main(String[] args) {
//定义person对象
Person person = new Person();
person.eat("鸡蛋西红柿");
person.eat("肉夹馍");
String result = person.study();
System.out.println(result);
}
}
2.3 对象的生命周期
在学习完类的设计与对象的创建语法之后,接下来我们讲解对象在jvm中运行的生命周期;首先我们完成一个示例,让后根据示例讲解jvm内存运行过程。
示例1:定义User类,类中有属性:id、name、age、phone;方法有showMessage展示用户信息
参考代码:
/**
定义User类,类中有属性:id、name、age、phone;方法有showMessage展示用户信息
*/
public class User {
// 用户唯一标识
int id;
// 姓名
String name;
// 年龄
int age;
// 手机号
String phone;
//展示用户信息
void showMessage(){
System.out.println("id:"+id+",name:"+name+",age:"+age+",phone:"+phone);
}
/*程序入口*/
public static void main(String[] args) {
//创建对象
User user = new User();
//赋值
user.id = 1;
user.name = "小红";
user.age = 18;
user.phone = "138389438";
//查看信息
user.showMessage();
//创建对象2
User user2 = new User();
//赋值
user2.id = 2;
user2.name = "小明";
user2.age = 19;
user2.phone = "138389538";
//查看信息
user2.showMessage();
}
}
在讲解user对象jvm运行过程之前,我们先复习以下jvm的内存结构
每块内存负责的职责如下:
-
Java虚拟机栈(Java Virtual Machine Stacks):描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧(Stack Frame),栈帧中存储着局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,会对应一个栈帧在虚拟机栈中入栈到出栈的过程。与程序计数器一样,Java虚拟机栈也是线程私有的。
局部变量和引用地址都是在栈内存中。
-
堆:此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java虚拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配。
-
方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法区存放的数据只有一份。
-
本地方法栈(Native Method Stack):与Java虚拟机栈作用很相似,它们的区别在于虚拟机栈为虚拟机执行Java方法(即字节码)服务,而本地方法栈则为虚拟机使用到的Native方法服务。例如调用本地c/c++的方法。
-
程序计数器:程序计数器是记录当前线程所执行指令的行数。
user对象的生命周期如下
2.4 练习
练习1:定义一个钟表类,属性有秒针,分钟针,时针。方法有runSecond(),runMinute(),runHour()来描述指针的运行,要求最后完成钟表正常运行。
参考答案:
public class Clock {
//1.定义秒针
int second;
//2.定义分钟针
int minute;
//4.定义小时针
int hour;
//5.定义运行秒针方法
void runSecond(){
second++;
if(second==60) {
second = 0;
//minute++;
runMinute();
}
}
//6.定义分钟针运行
void runMinute() {
minute++;
if(minute==60) {
minute=0;
//hour++;
runHour();
}
}
//7.定义小时
void runHour() {
hour++;
if(hour==24) {
hour = 0;
}
}
public static void main(String[] args) {
//1.创建钟表对象
Clock clock = new Clock();
//2.初始化值
clock.second = 10;
clock.minute = 51;
clock.hour = 15;
//3.打印时钟
while(true) {
//4.后面详细讲这个代码,这里只是测试,让程序听1000毫秒在执行
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("时钟:"+clock.hour+":"+clock.minute+":"+clock.second);
clock.runSecond();
}
}
}
类的访问机制:
- 在一个类中的访问机制:类中的方法可以直接访问类中的成员变量和成员方法。
- 在不同类中的访问机制:先创建要访问类的对象,再用对象访问类中定义的成员
2.5 小节
- 类与对象的关系
- 类的定义与对象的创建
- 对象在jvm的运行过程
- 类的访问机制
三、匿名对象
3.1 什么是匿名对象
像这种new Person()不保存对象内存地址的对象叫匿名对象
示例:
/**
* 匿名对象
*/
public class AnonymousObject {
void study(){
System.out.println("胖叔讲java");
}
/*程序入口*/
public static void main(String[] args) {
//匿名对象调用方法
new AnonymousObject().study();
// == 比较基本类型比较的是内容是否相等,比较引用类型比较的是地址是否相等
// 匿名对象是两个对象,所以地址不相等
System.out.println(new AnonymousObject()==new AnonymousObject());
}
}
jvm运行过程
3.2 应用场景
匿名对象的应用场景
- 如果对一个对象只需要进行一次方法调用,那么就可以使用匿名对象。
- 我们经常将匿名对象作为实参传递给一个方法调用
示例:
public class AnonymousObject2 {
int id = 1;
String name = "张三";
int age = 18;
}
public class AnonymousObject2Use {
public void useAnonymousObject2(AnonymousObject2 anonymousObject2){
System.out.println("id:"+anonymousObject2.id+",name:"+anonymousObject2.name+",age:"+anonymousObject2.age);
}
public static void main(String[] args) {
//匿名对象当作参数使用
AnonymousObject2Use anonymousObject2Use = new AnonymousObject2Use();
anonymousObject2Use.useAnonymousObject2(new AnonymousObject2());
}
}
四、类的成员详解
上边讲了类与对象的基本使用,我们在类中定义类属性和方法;其实类的成员包含很多内容,如下所示:
本章节详细讲解成员变量、方法、构造方法、其他类的成员会在后面章节详细讲解。
4.1 成员变量
4.1.1 成员变量与局部变量的区别
在方法体外,类体内声明的变量称为成员变量。在方法体内部声明的变量称为局部变量。成员变量和局部变量的区别如下:
示例1:成员变量与局部变量区别
/**
* 成员变量与局部变量的区别
*/
public class VariableDemo {
//成员变量可以被private、public、static、final修饰,这些修饰符含义后面详细讲解
private int id;
private String name;
/*程序入口*/
public static void main(String[] args) {
//局部变量只能用final修饰
//private int i; //报错
int j = 1;
//局部变量必须初始化才能使用
System.out.println(j);
//创建对象,成员变量有默认值
VariableDemo variableDemo = new VariableDemo();
System.out.println(variableDemo.id);
System.out.println(variableDemo.name);
}
}
4.1.2 成员变量的默认值
当一个对象被创建时,会对其中各种类型的成员变量自动进行初始化赋值。除了 基本数据类型之外的变量类型都是引用类型。具体默认值如下:
示例2:成员变量默认值
/**
* 成员变量默认值
*/
public class VariableDemo2 {
byte v1;
short v2;
int v3;
long v4;
float v5;
double v6;
char v7;
boolean v8;
/*程序入口*/
public static void main(String[] args) {
VariableDemo2 variableDemo2 = new VariableDemo2();
System.out.println(variableDemo2.v1);
System.out.println(variableDemo2.v2);
System.out.println(variableDemo2.v3);
System.out.println(variableDemo2.v4);
System.out.println(variableDemo2.v5);
System.out.println(variableDemo2.v6);
System.out.println(variableDemo2.v7);
System.out.println(variableDemo2.v8);
}
}
4.2 方法
什么是方法?
- 方法是类或对象行为特征的抽象,用来完成某个功能操作。在某些语言中也称为函数或过程。
- 将功能封装为方法的目的是,可以实现代码重用,简化代码
- Java里的方法不能独立存在,所有的方法必须定义在类里
4.2.1 方法的基本应用
定义方法的语法如下:
其中 :
- 修饰符:public, 缺省,private, protected等等
- 返回值类型:
- 没有返回值:void
- 有返回值,声明出返回值的类型。与方法体中“ “return ” 返回值” 搭配使用;返回值类型可以是基本类型和引用类型。
- 方法名 :属于标识符,命名时遵循标识符命名规则和规范,“ 见名知意”
- 形参列表:可以包含零个,一个或多个 参数。多个参数时,中间用“, ”隔开
- 返回值:方法在执行完毕后返还给调用它的程序的数据。
方法 的分类:按照是否有形参及返回值
注意:无返回的方法也可以使用return关键字,代表结束方法的执行。具体使用参照下面示例:
示例1:方法的分类演示
/**
* 方法定义的分类
*/
public class MethodDemo {
// 无参数,无返回值方法
void method1(){
System.out.println("胖叔讲java,一路相伴");
}
// 有参数,无返回值方法
void method2(String arg){
System.out.println("有参数无返回值方法,参数是:"+arg);
}
// 无参数,有返回值方法
String method3(){
return "结果"; //返回的内容必须和返回类型保持一致
}
// 有参数,有返回值方法
String method4(String arg){
System.out.println("有参数有返回值方法,参数是:"+arg);
return "结果2";
}
public static void main(String[] args) {
//创建对象
MethodDemo methodDemo = new MethodDemo();
//调用方法
methodDemo.method1();
methodDemo.method2("小红");
String result = methodDemo.method3();
System.out.println(result);
String result2 = methodDemo.method4("小明");
System.out.println(result2);
}
}
示例2:无返回值方法使用return关键字
/**
* 无返回值方法使用return关键字
*/
public class MethodDemo2 {
/**
* 需求:从1打印到指定目标数
*
* return 结束该方法运行。 返回值类型是void return 后面不加值,直接写分号。
*/
public void method1(int target){
int i = 1;
while(true){
System.out.println(i);
if(i==target){
return;
}
i++;
}
}
public static void main(String[] args) {
MethodDemo2 methodDemo2 = new MethodDemo2();
methodDemo2.method1(1100);
}
}
小结:
- 方法被调用一次,就会执行一次
- 没有具体返回值的情况,返回值类型用关键字void表示,那么方法体中可以不必使用return语句。如果使用,仅用来结束方法。
- 定义方法时,方法的结果应该返回给调用者,交由调用者处理。
- 方法中只能调用方法或属性,不可以在方法内部定义方法。
4.2.2 方法的重载
重载的概念:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
重载的特点:与返回值类型无关,只看参数列表,且参数列表必须不同。(参数个数或参数类型)。调用时,根据方法参数列表的不同来区别。
示例:返回两个数字/三个数字的和
package top.psjj.demo1;
/**
* 方法的重载,求两个数的和
*/
public class OverloadMethod {
int sum(int a,int b){
return a+b;
}
int sum(int a,int b,int c){
return a+b+c;
}
double sum(double a,double b){
return a+b;
}
double sum(double a,double b ,double c){
return a+b+c;
}
public static void main(String[] args) {
//创建对象
OverloadMethod overloadMethod = new OverloadMethod();
//调用方法:方法重载,优点:感觉上像是调用一个方法实现了多个功能,实际还是调用了多个方法。
int result = overloadMethod.sum(1, 2);
System.out.println(result);
double result2 = overloadMethod.sum(1.1, 2.2);
System.out.println(result2);
int result3 = overloadMethod.sum(1, 2, 3);
System.out.println(result3);
double result4 = overloadMethod.sum(1.1,2.2,3.3);
System.out.println(result4);
}
}
练习题1:编写程序,定义三个重载方法并调用。方法名为mol。三个方法分别接收一个int参数、两个int参数、一个字符串参数。分别 执行平方运算并输出结果,相乘并输出结果,输出字符串信息。 在主类的main ()方法中分别用参数区别调用三个方法。
练习题2:定义三个重载方法max(),第一个方法求两个int值中的最大值,第二个方 法求两个double值中的最大值,第三个方法求三个double值中的最大值, 并分别调用三个方法。
4.2.3 方法的可变参数
什么是可变参数?
JavaSE 5.0 中提供了Varargs(variable number of arguments)机制,允许直接定义能和多个实参相匹配的形参。从而,可以用一种更简单的方式,来传递个数可变的实参
可变参数语法:
- 声明格式:**方法名(参数的类型名 …参数名) **
- 可变参数:传递实参的个数是可变的,可以是0个,1个 ,2个 …
- 可变个数形参的方法与同名的方法之间,彼此构成重载
- 可变参数方法的使用与方法参数部分使用数组是一致的
- 方法的参数部分有可变形参,需要放在形参声明的最后
- 在一个方法的形参位置,最多只能声明一个可变个数形参
示例:通过可变参数计算n个数的最大值,最小值。
/**
* 可变参数:通过可变参数计算n个数的最大值,最小值。
*/
public class NumberUtils {
//args 代表参数
void printMaxAndMin(double... args) {
//1.可变参数的数据全部存放在args的数组中
double min;
double max;
if(args.length>0) {
//2.如果传入参数就初始化最大值和最小值
min = args[0];
max = args[0];
for(int i=0;i<args.length;i++) {
if(min>args[i]) {
min = args[i];
}
if(max<args[i]) {
max = args[i];
}
}
//3.打印最大值和最小值
System.out.println("最大值:"+max);
System.out.println("最小值:"+min);
} else {
System.out.println("没有传递参数无法计算最大值和最小值");
}
}
public static void main(String[] args) {
NumberUtils numberUtils = new NumberUtils();
numberUtils.printMaxAndMin(-1.1,2.2,3.3,9.3);
numberUtils.printMaxAndMin();
}
}
示例2:
/**
* 求n个整数的和,至少传入一个参数
*/
public class SumDemo {
//1.只可以有一个可变参数而且必须在最后
int sum(int number,int... args) {
int sum = 0;
sum+=number;
if(args.length>0) {
for(int i=0;i<args.length;i++) {
sum+=args[i];
}
}
return sum;
}
public static void main(String[] args) {
SumDemo sumDemo = new SumDemo();
int result = sumDemo.sum(1,2,3);
System.out.println(result);
}
}
练习题:通过可变参数计算n个数的最大值,最小值,和,平均值。
4.2.4 方法的值的传递机制
Java里方法的参数传递方式只有一种:值传递。 即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
- 形参是基本数据和String类型:将实参基本数据类型变量的“数据值”传递给形参
- 形参是引用数据类型:将实参引用数据类型变量的“地址值”传递给形参
示例1:测试方法参数传递是传递实际参数的副本
public class MethodDemo {
//Java里方法的参数传递方式只有一种:值传递。 即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
void method1(int i){
//改变参数值
i++;
System.out.println(i);
}
//Java里方法的参数传递方式只有一种:值传递。 即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。
void method2(User user){
//改变参数的地址
user = new User();
//给新地址重新赋值
user.id = 2;
user.name = "李四";
user.show();
}
public static void main(String[] args) {
//创建对象
MethodDemo methodDemo = new MethodDemo();
//将变量i传入method1方法中,是将i的副本传入方法中i的值不受影响
int i = 5;
methodDemo.method1(i);
System.out.println(i);
//将user对象传入method2方法中,是将user对象的内存地址副本传入方法中
User user = new User();
user.id = 1;
user.name = "张三";
// method2对传入的副本的地址更改了,对原来地址内容没有影响
methodDemo.method2(user);
user.show();
}
}
class User {
int id;
String name;
void show(){
System.out.println("id:"+id+",name:"+name);
}
}
示例2:当实际参数是基本类型和引用类型的区别
/**
* 值传递,基本类型和引用类型的区别
*/
public class MethodDemo2 {
//传递基本类型传递的是值的副本,方法体内改变参数的值不会影响外部变量
void method1(int i){
//改变参数值
i++;
System.out.println(i);
}
//传递引用类型传递的是值的副本,但是值的副本和外部变量却指向堆内存同一块内存地址
//所以改变改变user地址的内容,外部的对象的属性也就变了
void method2(User user){
user.id = 2;
user.name = "李四";
user.show();
}
public static void main(String[] args) {
MethodDemo2 methodDemo2 = new MethodDemo2();
//传递基本类型传递的是值的副本,方法体内改变参数的值不会影响外部变量
int i = 1;
methodDemo2.method1(i);
System.out.println(i);
//传递引用类型传递的是值的副本,但是值的副本和外部变量却指向堆内存同一块内存地址
//所以改变改变user地址的内容,外部的对象的属性也就变了
User user = new User();
user.id = 1;
user.name = "张三";
methodDemo2.method2(user);
user.show();
}
}
class User {
int id;
String name;
void show(){
System.out.println("id:"+id+",name:"+name);
}
}
练习题:定义一个数组工具类数组反转,数组排序。
小结:java参数传递机制只有一种,值传递,既将实参的复制品的值传入参数;如果是基本类型和String传递的数数据值,对外部变量没有影响;如果传递是引用类I型那个,传递的是地址值,可能堆外部变量有影响。
4.2.5 方法的递归
什么是递归?递归就是方法本身调用方法本身。
示例1:用方法打印1-100的数;
public class RecursiveDemo {
//1.用递归的方式:从1打印到100
void print(int i) {
if(i<=100) {
System.out.println(i);
i++;
print(i);
}
}
public static void main(String[] args) {
RecursiveDemo recursiveDemo = new RecursiveDemo();
recursiveDemo.print(1);
}
}
示例2:递归必须指定程序出口,否者报错:StackOverflowError 栈溢出错误
public class RecursiveDemo2 {
//递归调用没有指定方法出口,无限调用
void print(int i) {
System.out.println(i);
i++;
print(i);
}
public static void main(String[] args) {
RecursiveDemo2 recursiveDemo2 = new RecursiveDemo2();
recursiveDemo2.print(1);
}
}
练习题1:请用递归计算出1-100的和
练习题2:请用Java写出递归求阶乘(n!)的算法
4.3 构造方法
4.3.1 构造方法的基本使用
在java类中定义的构造方法是用来创建对象的,它的定义语法如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G7N3U0eZ-1658146485325)(assets/14.png)]
示例1:在User类型中定义构造方法并使用
public class User {
int id;
String name;
int age;
//定义构造方法
User(int userId,String userName,int userAge){
id = userId;
name = userName;
age = userAge;
}
public static void main(String[] args) {
//使用构造方法创建对象
User user = new User(1,"张三",21);
//查看user信息
System.out.println("id:"+user.id+",name:"+user.name+",age:"+user.age);
}
}
4.3.2 构造方法的重载
构造方法是一种特殊的方法,也可以进行方法的重载;
示例1:
public class User {
int id;
String name;
int age;
//定义构造方法
User(int userId,String userName,int userAge){
id = userId;
name = userName;
age = userAge;
}
//构造方法的重载
User(int userId,String userName){
id = userId;
name = userName;
}
User(){
}
public static void main(String[] args) {
//使用构造方法创建对象
User user = new User(1,"张三",21);
//查看user信息
System.out.println("id:"+user.id+",name:"+user.name+",age:"+user.age);
//创建对象,查看用户信息
User user2 = new User(2,"李四");
System.out.println("id:"+user2.id+",name:"+user2.name+",age:"+user2.age);
//创建对象,查看用户信息
User user3 = new User();
System.out.println("id:"+user3.id+",name:"+user3.name+",age:"+user3.age);
}
}
4.3.3 默认构造方法
在一个类中如果没定义构造方法,系统会默认定义一个无参数的构造方法;在一个类中如果定义了构造方法,系统将不会默认定义构造方法
示例1:
public class Person {
int id;
String name;
/**
* 当类中没有定义构造方法时,系统会默认定义如下构造方法
*/
/*public Person(){
}*/
/**
* 当类中定义了构造方法时,系统不会默认定义构造方法
*/
public Person(int personId,String personName){
id = personId;
name = personName;
}
public static void main(String[] args) {
//创建对象
Person person = new Person();
}
}
4.3.4 构造方法注意事项
使用构造方法时需要注意以下几点:
- 它具有与类相同的名称
- 它不声明返回值类型。(与声明为void不同)
- 不能被static、final、synchronized、abstract 等修饰,不能有 return语句返回值
- 构造方法是一种特殊的方法,支持重载
4.4 小结
-
成员变量与局部变量的区别
-
成员变量的默认值
-
方法的重载
-
可变参数
-
方法的值传递机制
-
方法的递归
-
构造方法
五、this关键字
5.1 this关键字概述
在Java中,this关键字比较难理解,它的作用和其词义很接近。单词含义是这个 的意思 。this关键字可以使用在方法和构造方法体内。
- 它在方法内部使用,即这个方法所属对象的引用;
- 它在构造器内部使用,表示该构造器正在初始化的对象。
- this 可以调用类的属性、方法和构造器
5.2 this 入门案例
我们先看如下案例,发现构造方法的参数名不能和成员变量名一样,否者无法初始化;示例代码如下:
public class User {
int id;
String name;
int age;
/**
*java 使用变量有就近原则 从当前最近{} 范围查找变量,找到就是使用,找不到才去成员变量找
* 所以,这里面的id=id name = name age=age其实是参数给参数自己赋值,根本没有调用成员变量
*/
/* User(int id,String name,int age){
id = id;
name = name;
age = age;
}*/
// this关键字,表示该构造方法正在初始化的对象
User(int id,String name,int age){
this.id = id;
this.name = name;
this.age = age;
}
void show(){
System.out.println("id:"+id+",name:"+name+",age:"+age);
}
/*程序入口*/
public static void main(String[] args) {
User user = new User(1,"张三",18);
user.show();
User user2 = new User(2,"李四",19);
user2.show();
}
}
5.3 this关键字应用场景
this关键字可以使用在方法和构造方法体内。
- 它在方法内部使用,即这个方法所属对象的引用;
- 它在构造器内部使用,表示该构造器正在初始化的对象。
- this 可以调用类的属性、方法和构造器
示例1:this在构造方法中应用
public class User {
int id;
String name;
int sex;
User(int id,String name,int sex){
//this代表当前正在初始化的user对象,
// 含义是user.id = id; user.name = name user.sex = sex;
//但此时只能通过this引用正在初始化的对象。
this.id = id;
this.name = name;
this.sex = sex;
}
User(int id,String name){
// this(参数列表)调用的是构造方法 调用的上面的构造方法
this(id,name,0);
// 代表当前正在初始化的user对象 this.show()等价于user.show(),但此时只能通过this引用正在初始化的对象。
this.show();
}
void show(){
System.out.println("id:"+id+",name:"+name+",sex:"+sex);
}
/*程序入口*/
public static void main(String[] args) {
User user = new User(1,"张三");
}
}
示例2:this在普通方法中应用
public class User {
int id;
String name;
int sex;
User(int id, String name, int sex) {
this.id = id;
this.name = name;
this.sex = sex;
}
void method1(){
System.out.println("方法");
}
void show(){
//在方法中不可以调用构造器,不能使用this(1,"张三",1);
//当前方法所属对象调用method1()
this.method1();
//当前方法所属对象 id name sex 属性
System.out.println("id:"+this.id+",name:"+this.name+",sex:"+this.sex);
}
}
5.4 小结
this可以使用在构造器和方法中,在构造器中可以使用
- this.属性
- this.方法
- this(构造方法参数列表)
在普通方法中可以使用
- this.属性
- this.方法
六、总结
- 类与对象
- 成员变量
- 成员方法
- 方法重载
- 可变参数
- 值传递
- 递归
- 构造方法
- this关键字应用