39-面向对象编程(基础)3

方法重载

基本介绍

java中允许同一个类中,多个同名方法的存在,但要求形参列表一致
比如:System.out.println() ; out 是printStream类

重载的好处

  1. 减轻了起名的麻烦
  2. 减轻了记名的麻烦

快速入门

public class OverLoad01 { 

	//编写一个main方法
	public static void main(String[] args) {

		// System.out.println(100);
		// System.out.println("hello,world");
		// System.out.println('h');
		// System.out.println(1.1);
		// System.out.println(true);
		// 
		MyCalculator mc = new MyCalculator();
		System.out.println(mc.calculate(1, 2));
		System.out.println(mc.calculate(1.1, 2));
		System.out.println(mc.calculate(1, 2.1));
	}
}

class MyCalculator  {

	//下面的四个 calculate方法构成了重载
	//两个整数的和
	public int calculate(int n1, int n2)  {
		System.out.println("calculate(int n1, int n2) 被调用");
		return n1 + n2;
	}

	//没有构成方法重载, 仍然是错误的,因为是方法的重复定义
	// public void calculate(int n1, int n2)  {
	// 	System.out.println("calculate(int n1, int n2) 被调用");
	// 	int res =  n1 + n2;
	// } 

	//看看下面是否构成重载, 没有构成,而是方法的重复定义,就错了
	// public int calculate(int a1, int a2)  {
	// 	System.out.println("calculate(int n1, int n2) 被调用");
	// 	return a1 + a2;
	// } 

	//一个整数,一个double的和
	public double calculate(int n1, double n2) {
		return n1 + n2;
	}
	//一个double ,一个Int和 
	public double calculate(double n1, int n2) {
		System.out.println("calculate(double n1, int n2) 被调用..");
		return n1 + n2;
	}
	//三个int的和
	public int calculate(int n1, int n2,int n3) {
		return n1 + n2 + n2;
	}

}

注意事项和使用细节

  1. 方法名:必须相同
  2. 形参列表:必须不同(形成类型或个数或顺序,至少有一样不同,参数名无要求)
  3. 返回类型:无要求
    eg:
    请添加图片描述

可变参数

基本概念

java允许将同一个类中多个同名功能但参数个数不同的方法,封装成一个方法,就可以通过可变参数实现

基本语法

访问修饰符 返回类型 方法名(数据类型... 参数名){
}

快速入门

public class VarParameter01 { 

	//编写一个main方法
	public static void main(String[] args) {

		HspMethod m = new HspMethod();
		System.out.println(m.sum(1, 5, 100)); //106
		System.out.println(m.sum(1,19)); //20
	}
}

class HspMethod {
	//可以计算 2个数的和,3个数的和 , 4. 5, 。。
	//可以使用方法重载
	// public int sum(int n1, int n2) {//2个数的和
	// 	return n1 + n2;
	// }
	// public int sum(int n1, int n2, int n3) {//3个数的和
	// 	return n1 + n2 + n3;
	// }
	// public int sum(int n1, int n2, int n3, int n4) {//4个数的和
	// 	return n1 + n2 + n3 + n4;
	// }
	//.....
	//上面的三个方法名称相同,功能相同, 参数个数不同-> 使用可变参数优化
	//老韩解读
	//1. int... 表示接受的是可变参数,类型是int ,即可以接收多个int(0-多) 
	//2. 使用可变参数时,可以当做数组来使用 即 nums 可以当做数组
	//3. 遍历 nums 求和即可
	public int sum(int... nums) {
		//System.out.println("接收的参数个数=" + nums.length);
		int res = 0;
		for(int i = 0; i < nums.length; i++) {
			res += nums[i];
		}
		return res;
	}
}

使用细节

  1. 可变参数的实参可以为0个或者任意个
  2. 可变参数的实参可以为数组
  3. 可变参数的本质就是数组
  4. 可变参数可以和普通类型的参数放在形参列表,但必须保证可变参数在最后
  5. 一个形参列表中只能出现一个可变参数
public class VarParameterDetail { 

	//编写一个main方法
	public static void main(String[] args) {
		//细节: 可变参数的实参可以为数组
		int[] arr = {1, 2, 3};
		T t1 = new T();
		t1.f1(arr);
	}
}

class T {

	public void f1(int... nums) {
		System.out.println("长度=" + nums.length);
	}

	//细节: 可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
	public void f2(String str, double... nums) {

	}
	//细节: 一个形参列表中只能出现一个可变参数
	//下面的写法是错的.
	// public void f3(int... nums1, double... nums2) {

	// }
}

练习

请添加图片描述

public class VarParameterExercise { 

	//编写一个main方法
	public static void main(String[] args) {
		HspMethod hm = new HspMethod();
		System.out.println(hm.showScore("milan" , 90.1, 80.0 ));
		System.out.println(hm.showScore("terry" , 90.1, 80.0,10,30.5,70 ));
	}
}

class HspMethod  {

	/*
	有三个方法,分别实现返回姓名和两门课成绩(总分),
	返回姓名和三门课成绩(总分),返回姓名和五门课成绩(总分)。
	封装成一个可变参数的方法
	 */
	
	//分析1. 方法名 showScore  2. 形参(String ,double... ) 3. 返回String
	//听课小伙伴,老师要求必须自己动手写
	public String  showScore(String name ,double... scores ) {

		double totalScore = 0;
		for(int i = 0; i < scores.length; i++) {
			totalScore += scores[i];
		}
		return name + " 有 " +scores.length + "门课的成绩总分为=" + totalScore;
	}
 }

作用域

基本介绍

在这里插入图片描述

public class VarScope { 

	//编写一个main方法
	public static void main(String[] args) {
	}
}
class Cat {
	//全局变量:也就是属性,作用域为整个类体 Cat类:cry eat 等方法使用属性
	//属性在定义时,可以直接赋值
	int age = 10; //指定的值是 10

	//全局变量(属性)可以不赋值,直接使用,因为有默认值,
	double weight;  //默认值是0.0

	public void hi() {
		//局部变量必须赋值后,才能使用,因为没有默认值
		int num = 1;
		String address = "北京的猫";
		System.out.println("num=" + num);
		System.out.println("address=" + address);
		System.out.println("weight=" + weight);//属性
	}
	
	public void cry() {
		//1. 局部变量一般是指在成员方法中定义的变量
		//2. n 和  name 就是局部变量
		//3. n 和 name的作用域在 cry方法中
		int n = 10;
		String name = "jack";
		System.out.println("在cry中使用属性 age=" + age);
	}

	public void eat() {

		System.out.println("在eat中使用属性 age=" + age);
		

		//System.out.println("在eat中使用 cry的变量 name=" + name);//错误
	}
}

细节

  1. 属性和局部变量可以重名,访问时遵循就近原则
  2. 在同一个作用域中,比如在同一个方法中,两个局部变量,不能重名
  3. 属性生命周期长,伴随着对象的创建二创建,伴随对象的销毁而销毁。局部变量,生命周期短,伴随着它的代码块的执行而创建,伴随这代码块的结束而销毁。即在一次方法调用的过程中
  4. 作用域范围不同
    全局变量/属性:可以被本类使用,或其他类使用(通过对象调用)
    局部变量:只能在本类中对应的方法使用
  5. 修饰符不同
    全局变量/属性可以加修饰符
    局部变量不可以加修饰符
public class VarScopeDetail { 

	//编写一个main方法
	public static void main(String[] args) {
		Person p1 = new Person();
		/*
		属性生命周期较长,伴随着对象的创建而创建,伴随着对象的销毁而销毁。
		局部变量,生命周期较短,伴随着它的代码块的执行而创建,
		伴随着代码块的结束而销毁。即在一次方法调用过程中
		 */
		//p1.say();//当执行say方法时,say方法的局部变量比如name,会创建,当say执行完毕后
		//name局部变量就销毁,但是属性(全局变量)仍然可以使用
		//
		T t1 = new T();
		t1.test(); //第1种跨类访问对象属性的方式

		t1.test2(p1);//第2种跨类访问对象属性的方式

	}
}

class T {

	//全局变量/属性:可以被本类使用,或其他类使用(通过对象调用)
	public void test() {
		Person p1 = new Person();
		System.out.println(p1.name);//jack
	}

	public void test2(Person p) {
		System.out.println(p.name);//jack
	}
}

class Person {
	//细节: 属性可以加修饰符(public protected private..)
	//      局部变量不能加修饰符
	public int age = 20;

	String name = "jack";

	public void say() {
		//细节 属性和局部变量可以重名,访问时遵循就近原则
		String name = "king";
		System.out.println("say() name=" + name);
	}

	public void hi() {
		String address = "北京";
		//String address = "上海";//错误,重复定义变量
		String name = "hsp";//可以
	}
}

构造器

基本介绍

请添加图片描述

基本语法

请添加图片描述

快速入门

public class Constructor01 { 

	//编写一个main方法
	public static void main(String[] args) {
		//当我们new 一个对象时,直接通过构造器指定名字和年龄
		Person p1 = new Person("smith", 80);
		System.out.println("p1的信息如下");
		System.out.println("p1对象name=" + p1.name);//smith
		System.out.println("p1对象age=" + p1.age);//80
	}
}

//在创建人类的对象时,就直接指定这个对象的年龄和姓名
//
class Person {
	String name;
	int age;
	//构造器
	//老韩解读
	//1. 构造器没有返回值, 也不能写void
	//2. 构造器的名称和类Person一样
	//3. (String pName, int pAge) 是构造器形参列表,规则和成员方法一样
	public  Person(String pName, int pAge) {
		System.out.println("构造器被调用~~ 完成对象的属性初始化");
		name = pName;
		age = pAge;
	}
}

使用细节

在这里插入图片描述
在这里插入图片描述

public class ConstructorDetail { 

	//编写一个main方法
	public static void main(String[] args) {
		Person p1 = new Person("king", 40);//第1个构造器
		Person p2 = new Person("tom");//第2个构造器

		Dog dog1 = new Dog();//使用的是默认的无参构造器

	}
}
class Dog {
	//如果程序员没有定义构造器,系统会自动给类生成一个默认无参构造器(也叫默认构造器)
	//使用javap指令 反编译看看
	/*
		默认构造器
		Dog() {
			
		}
	 */
	//一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器,
	//除非显式的定义一下,即:  Dog(){}  写 (这点很重要)
	//
	public Dog(String dName) {
		//...
	}
	Dog() { //显式的定义一下 无参构造器

	}
}

class Person {
	String name;
	int age;//默认0
	//第1个构造器
	public Person(String pName, int pAge) {
		name = pName;
		age = pAge;
	}
	//第2个构造器, 只指定人名,不需要指定年龄
	public Person(String pName) {
		name = pName;
	}
}

练习

在这里插入图片描述

public class ConstructorExercise { 

	//编写一个main方法
	public static void main(String[] args) {
		Person p1 = new Person();//无参构造器

		//下面输出 name = null, age = 18
		System.out.println("p1的信息 name=" + p1.name + " age=" + p1.age);

		Person p2 = new Person("scott", 50);
		//下面输出 name = scott, age = 50
		System.out.println("p2的信息 name=" + p2.name + " age=" + p2.age);

	}
}

/**
 * 在前面定义的Person类中添加两个构造器:
 * 第一个无参构造器:利用构造器设置所有人的age属性初始值都为18
 * 第二个带pName和pAge两个参数的构造器:
 * 使得每次创建Person对象的同时初始化对象的age属性值和name属性值。
 * 分别使用不同的构造器,创建对象.
 */

class Person {
	String name;//默认值 null
	int age;//默认 0
	//第一个无参构造器:利用构造器设置所有人的age属性初始值都为18
	public Person() {
		age = 18;//
	}
	//第二个带pName和pAge两个参数的构造器
	public Person(String pName, int pAge) {
		name = pName;
		age = pAge;
	}
}

对象创建流程详解

请添加图片描述请添加图片描述

This关键字

基本介绍

java虚拟机会给每个对象分配this,代表当前对象

public class This01 { 

	//编写一个main方法
	public static void main(String[] args) {

		Dog dog1 = new Dog("大壮", 3);
		System.out.println("dog1的hashcode=" + dog1.hashCode());
		//dog1调用了 info()方法
		dog1.info(); 

		System.out.println("============");
		Dog dog2 = new Dog("大黄", 2);
		System.out.println("dog2的hashcode=" + dog2.hashCode());
		dog2.info();
	}
}

class Dog{ //类

	String name;
	int age;
	// public Dog(String dName, int  dAge){//构造器
	// 	name = dName;
	// 	age = dAge;
	// }
	//如果我们构造器的形参,能够直接写成属性名,就更好了
	//但是出现了一个问题,根据变量的作用域原则
	//构造器的name 是局部变量,而不是属性
	//构造器的age  是局部变量,而不是属性
	//==> 引出this关键字来解决
	public Dog(String name, int  age){//构造器
		//this.name 就是当前对象的属性name
		this.name = name;
		//this.age 就是当前对象的属性age
		this.age = age;
		System.out.println("this.hashCode=" + this.hashCode());
	}

	public void info(){//成员方法,输出属性x信息
		System.out.println("this.hashCode=" + this.hashCode());
		System.out.println(name + "\t" + age + "\t");
	}
}

this本质

请添加图片描述
小结:简单的说,哪个对象调用,this就代表哪个对象

this使用细节

  1. this关键字可以用来访问本类的属性,方法,构造器
  2. this用于区分当前类的属性和局部变量
  3. 访问成员方法的语法:this.方法名(形参列表);
  4. 访问构造器方法:this(形参列表);
    (注意:只能在构造器中访问另一个构造器,必须放在第一条语句)
  5. this 不能在类定义的外部使用,只能在类定义的方法中使用
public class ThisDetail { 

	//编写一个main方法
	public static void main(String[] args) {

		// T t1 = new T();
		// t1.f2();
		T t2 = new T();
		t2.f3();

	}
}

class T {

	String name = "jack";
	int num = 100;

	/*
	细节: 访问构造器语法:this(参数列表); 
	注意只能在构造器中使用(即只能在构造器中访问另外一个构造器)

	注意: 访问构造器语法:this(参数列表); 必须放置第一条语句 
	 */
	
	public T() {
		//这里去访问 T(String name, int age) 构造器
		this("jack", 100);
		System.out.println("T() 构造器");
		
	}

	public T(String name, int age) {

		System.out.println("T(String name, int age) 构造器");
	}

	//this关键字可以用来访问本类的属性
	public void f3() {
		String name = "smith";
		//传统方式
		System.out.println("name=" + name + " num=" + num);//smith  100
		//也可以使用this访问属性
		System.out.println("name=" + this.name + " num=" + this.num);//jack 100
	}
	//细节: 访问成员方法的语法:this.方法名(参数列表);
	public void f1() {

		System.out.println("f1() 方法..");
	}

	public void f2() {
		System.out.println("f2() 方法..");
		//调用本类的 f1
		//第一种方式
		f1();
		//第二种方式
		this.f1();
	}
	
}

练习

请添加图片描述

public class TestPerson { 

	//编写一个main方法
	public static void main(String[] args) {

		Person p1 = new Person("mary", 20);
		Person p2 = new Person("mary", 20);

		System.out.println("p1和p2比较的结果=" + p1.compareTo(p2));
	}
}

/*
定义Person类,里面有name、age属性,并提供compareTo比较方法,
用于判断是否和另一个人相等,提供测试类TestPerson用于测试, 
名字和年龄完全一样,就返回true, 否则返回false

 */
class Person {
	String name;
	int age;
	//构造器
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	//compareTo比较方法
	public boolean compareTo(Person p) {
		//名字和年龄完全一样
		// if(this.name.equals(p.name) && this.age == p.age) {
		// 	return true;
		// } else {
		// 	return false;
		// }
		return this.name.equals(p.name) && this.age == p.age;
	}
}

最后

附上韩顺平老师这节内容的章节总结原视频有助于知识梳理

进度263/910 ,学习永无止境!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值