8-Java类与对象

类与对象

  • 引入类
// 类与对象
// 一个程序就是一个世界,有很多事物(对象[属性, 行为])

public class Object01{

	public static void main(String[] args) {
		
		/*
		张老太养了两只猫,一只猫的名字叫小白,今年三岁,白色
		一只叫小花,今年100岁,请编写一个程序,当用户输入小猫的名字时,
		就显示这个猫的年龄,名字,颜色,如果用户的输入小猫名有误
		显示 张老太没有这只猫
		 */
		
		// 单独变量来解决 => 不利于数据的管理(把一只猫的数据拆解)
		// 第一只猫的信息
		String cat1Name = "小白";
		int cat1Age = 3;
		String cat1Color = "白色";

		// 第二只猫的信息
		String cat2Name = "小花";
		int cat2Age = 100;
		String cat2Color = "花色";


		// 数组  ===> 数据类型不能体现出来,
		// 只能通过下标获取信息,造成变量名字和内容对应关系不明确
		// 不能体现猫的行为
		// 第一只猫的信息
		// String[] cat1 = {"小白", "3", "白色"};
		// String[] cat2 = {"小花", "100", "花色"};


		// 现有技术的缺点
		// 不利于数据的管理
		// 效率低,引出我们新的知识点,类和对象
		// java的设计者引入类与对象(OOP),根本原因是现有的技术不能完美的解决新的需求
		// 
		// 
		// 
		// 使用OOP面向对象解决
		// 实例化一只猫【创建一个猫对象】
		// 1.new Cat()  创建一只猫
		// 2.Cat cat1 = new Cat();把创建的猫赋值给cat1
		Cat cat1 = new Cat();
		cat1.name = "小白";
		cat1.age = 3;
		cat1.color = "白色";
		cat1.weight = 10;

		// 创建第二只猫对象
		Cat cat2 = new Cat();
		cat2.name = "小花";
		cat2.age = 100;
		cat2.color = "花色";
		cat2.weight = 23.9;

	
		// 怎么使用,怎么访问对象的属性
		System.out.println("第一只猫的信息" + cat1.name + " " + cat1.age + " " + cat1.color + " " + cat1.weight);
		System.out.println("第一只猫的信息" + cat2.name + " " + cat2.age + " " + cat2.color + " " + cat2.weight);


	}
}

// 使用面向对象的方式解决养猫问题
// 定义一个猫类 Cat - > 自定义数据类型
// 
class Cat{

	// 属性
	String name;
	int age;
	String color;
	double weight;
}

  • 类在内存中的存在形式(重要)

public class Object02{

	public static void main(String[] args) {
		
	}
}

class Car{
	String name; // 属性 成员变量 字段  field
	double price;
	String color;
	String[] master; // 属性可以是基本数据类型,也可以是引用类型
}
  • 属性的注意事项
  1. 属性的定义语法同变量,示例:访问修饰符 属性类型 属性名;
    这里老师简单的介绍访问修饰符: 控制属性的访问范围 有四种访问修饰符 public, proctected, 默认, private ,后面我会详细介绍
  2. 属性的定义类型可以为任意类型,包含基本类型或引用类型
  3. 属性如果不赋值,有默认值,规则和数组一致。具体说: int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char \u0000, boolean false,String null
public class Properties{
	public static void main(String[] args) {
		
		// 创建对象
		// p1 是对象名(对象引用
		// new Perso() 创建的对象空间才是真正的对象
		Person p1 = new Person();

		// 对象的属性默认值,遵守数据的规则
		System.out.println("当前人的信息");
		System.out.println("age=" + p1.age + " name = " + p1.name + " sal=" + p1.sal + " isPass " + p1.isPass);
	}
}

class Person{

	int age;
	String name;
	double sal;
	boolean isPass;
}
  • 类的内存结构
  1. 栈: 一般存放基本数据类型(局部变量)
  2. 堆: 存放对象(Cat cat , 数组等)
  3. 方法区:常量池(常量,比如字符串), 类加载信息
  4. 示意图 [Cat (name, age, price)]

public class Object03{
	public static void main(String[] args) {
		
		Person p1 = new Person();
		p1.age = 10;
		p1.name = "小明";

		Person p2 = p1;

		p2.age = 80;
		System.out.println(p1.age); // 10

	}
}

class Person{
	String name;
	int age;

}

成员方法

  • 成员方法入门

public class Method01{

	public static void main(String[] args) {
		// 方法写好了,如果不去调用,不会输出
		// 如何使用方法,先创建一个对象,然后调用方法即可
		Person p1 = new Person();
		p1.speak(); // 调用方法
		p1.cal01();
		p1.cal02(5);
		p1.cal02(100);

		// 调用getSum方法,同时num1,num2
		// 把方法 getSum 返回的值赋给变量 returnRes
		int returnRes = p1.getSum(10, 20); // 
		System.out.println("getSum 方法返回的值:" + returnRes);


	}
}

class Person{
	String name;
	int age;

	// 方法,成员方法
	// 输出我是一个好人
	// 1.public 表示方法是公开的
	// 2. void 表示方法没有返回值
	// 3. speak(),speak就是方法的名称,()形参列表,当前没有任何值在里面
	// 4.{}方法体,可以写我们要执行的代码
	// 
	public void speak(){
		System.out.println("我是一个好人");
	}


	public void cal01(){
		// 循环完成
		int sum = 0;
		for(int i = 1; i <= 1000; i++){
			sum += i;
		}
		System.out.println("cal01计算结果:"  + sum);
	}

	// 接受一个参数n, 计算1 + 2 + ... + n
	// 形参列表,当前有个形参n,形参就是形式参数,可以接收用户的输入
	
	public void cal02(int n){
		int sum = 0;

		for(int i = 1; i <= n; i++){
			sum += i;

		}
		System.out.println("cal02计算结果:" + sum);

	}
	// 添加getSum方法,可以计算两个数的和
	// 1.public 表示方法是公开的
	// 2. int 表示返回一个int值
	// 3.(int num1, int num2) 形参列表,2个形参
	// 4.return res 表示把res的值返回
	public int getSum(int num1, int num2){
		int result = num1 + num2;

		return result;
	}

}
  • 方法的内存调用机制
  • 提高了代码的复用性,方法的最大优势,就是实现一个模块,可以多次复用
  • 可以将实现的细节封装起来,然后共其他用户调用即可
public class Method02{

	public static void main(String[] args) {
		
		// 遍历一个二维数组,输出数组的各个元素值
		
		int[][] map = {{0, 0, 1}, {1, 1, 1}, {1, 2, 3}};

		// for(int i = 0; i < map.length; i++){
		// 	for(int j = 0; j < map[i].length; j++){
		// 		System.out.print(map[i][j] + " ");
		// 	}

		// 	System.out.println();
		// }


		// // 要求再次遍历这个map数组
		// for(int i = 0; i < map.length; i++){
		// 	for(int j = 0; j < map[i].length; j++){
		// 		System.out.print(map[i][j] + " ");
		// 	}

		// 	System.out.println();
		// }

		// // 再次遍历,在复制一次
		// for(int i = 0; i < map.length; i++){
		// 	for(int j = 0; j < map[i].length; j++){
		// 		System.out.print(map[i][j] + " ");
		// 	}

		// 	System.out.println();
		// }
		// 
		// 使用方法进行输入
		myTools tool =  new myTools();
		tool.printArray(map);
	}
}

// 把输入的功能,写入到类的方法中,然后调用这个方法即可
class myTools{
	// 接受一个二维数组
	// 
	public void printArray(int[][] map){
		// 对传入的map数组进行遍历
		for(int i = 0; i < map.length; i++){
			for(int j = 0; j < map[i].length; j++){
				System.out.print(map[i][j] + " ");
			}

			System.out.println();
		}

	}

}
  • 成员方法的定义
    public 返回数据类型 方法名(形参){
    语句;
    返回值
    }

成员方法注意事项

  1. 访问控制符,作用是控制方法使用的范围,默认有四种(public protected, 默认,private)
  2. 一个方法最多有一个返回值
  1. 返回类型可以为任意类型,包含基本类型或引用类型(数组,对象)
  2. 如果方法要求有返回数据类型,则方法体中最后的执行语句必须为 return 值; 而且要求返回值类型必须和 return 的 值类型一致或兼容
  3. 如果方法是 void,则方法体中可以没有 return 语句,或者 只写 return ;
public class MethodDetail{
	public static void main(String[] args) {
		

		// 1个方法最多有一个返回值,思考如何返回多个值,数组
		// 2.返回类型可以为任何类型,包含基本类型和引用类型,数组,对象
		// 3.如果方法要求有返回值类型,则必须有return值
		// 而且要求return的值必须与return的值类型一致或者兼容
		// 
		// 4.如果是void,可以不写return或者return ,不能写其他
		AA a = new AA();

		int[] res = a.getSumAndSub(1, 4);

		double b = a.f1();
		System.out.println("和=" + res[0]);
		System.out.println("差=" + res[1]);
	}
}

class AA{
	public int[] getSumAndSub(int n1, int n2){
		int[] resArr = new int[2];

		resArr[0] = n1 + n2;
		resArr[1] = n1 - n2;

		return resArr;
	}

	public double f1(){

		double d1 = 1.1 * 3;
		int n = 100;
		return n;
	}
}

方法的注意细节

  • 同一个类的方法直接调用, 不需要创建对象
  • 不同类之间的方法调用,需要在该类创建一个新的对象,才能使用别的方法

 public class MethodDetail02{

 	public static void main(String[] args) {
 		A a = new A();
 		a.sayOk();
 		a.m1();

 	}
 }

 class A{
 	// 同一个类的方法直接调用, 不需要创建对象
 	// 
 	public void print(int n){
 		System.out.println("print方法被调用  n = " + n);
 	}

 	public void sayOk(){
 		print(10);

 		System.out.println("继续执行sayOk");
 	}

 	// 跨类中的A类调用B类方法:需要通过对象名进行调用
 	// 
 	public void m1(){
 		// 创建B对象
 		System.out.println("A类中的m1被调用");
 		B b = new B();
 		b.hi();
 		System.out.println("M1方法继续执行");

 	}
 }

 class B{
 	// 跨内的方法,需要创建方法
 	// 
 	public void hi(){
 		System.out.println("B类的hi方法执行");
 	}
 }
  • 练习1 返回一个数是否是奇数
public class MethodEx01{

	public static void main(String[] args) {
		
		// 
		AA a = new AA();
		boolean isRight = a.isOdd(5);
		System.out.println("5是奇数?" + isRight);
	}
}


class AA{
	// 思路
	// 1 方法的返回类型是 boolean
	// 2 方法的名字是 isOdd
	// 3 方法的形参是 int num
	// 4 方法体进行判断
	public boolean isOdd(int num){

		// boolean isRight = false;
		// if(n % 2 == 1){
		// 	isRight = true;
		// }
		// return isRight;
		// 
		// return num % 2 != 0 ? true: false;
		// 
		return num % 2 != 0;

	}
}
  • 练习2 输出一个行, 列,字符,打印这些字符
public class MethodEx01{

	public static void main(String[] args) {
		
		// 
		AA a = new AA();
		boolean isRight = a.isOdd(5);
		// System.out.println("5是奇数?" + isRight);
		
		// 调用方法
		a.printChar(4, 5, '*');
	}
}


class AA{
	// 思路
	// 1 方法的返回类型是 boolean
	// 2 方法的名字是 isOdd
	// 3 方法的形参是 int num
	// 4 方法体进行判断
	public boolean isOdd(int num){

		// boolean isRight = false;
		// if(n % 2 == 1){
		// 	isRight = true;
		// }
		// return isRight;
		// 
		// return num % 2 != 0 ? true: false;
		// 
		return num % 2 != 0;

	}

	// 思路
	// 1 没有返回值
	// 2 参数是三个,一个是行,一个是列,一个是字符
	// 3 打印二维数组的思想
	
	public void printChar(int row, int col, char chara){
		for(int i = 0 ; i < row; i++){
			for(int j=0; j < col; j++){
				System.out.print(chara + " ");
			}

			System.out.println();
		}
	}

}

成员变量传参机制

  • 传入的是基本数据类型,不会改变数据

public class MethodParameter01{
	public static void main(String[] args) {
		
		int a = 10;
		int b = 20;

		// 创建AA对象
		AA obj = new AA();
		obj.swap(a, b); // 调用swap方法
		System.out.println("a和b经过swap的值a=" + a + "\tb=" + b);
	}
}

class AA{

	public void swap(int a , int b){

		System.out.println("a和b交换前的值a=" + a + "\tb=" + b);
		// 完成a和b的交换
		// 
		int temp = a;
		a = b;
		b = temp;
		System.out.println("a和b交换后的值a=" + a + "\tb=" + b);
	}
}
  • 传入的是引用数据类型
    传入的是引用类型,由于传入的是地址,所以引用数据类型会改变

public class MethodParameter02{

	public static void main(String[] args) {
		B b = new B();
		int[] arr01 = {1, 2, 3};
		b.test100(arr01);

		System.out.println("main中的arr数组");
		for(int i= 0; i < arr01.length; i++){
			System.out.print(arr01[i] + "\t");
		}


	}
}

class B{

	// 接受一个数组,修改这个数组
	public void test100(int[] arr){

		arr[0] = 200;

		// 遍历数组
		System.out.println("类B中test100方法中");
		for(int i= 0; i < arr.length; i++){
			System.out.print(arr[i] + "\t");
		}

		
	}
}
  • 练习1,如何复制一个新的空间的类

public class MethodEx02{

	public static void main(String[] args) {
		
		//
		Person p =  new Person();
		p.name = "Tom";
		p.age = 12;

		MyTools tools =  new MyTools();

		Person p2 = tools.copyPerson(p);

		System.out.println("p2的name值:" + p2.name + " p2的age值:" + p2.age);
		p2.name = "小明";
		// 提示,可以通过hashCode看看对象是否是同一个
		// 可以通过对象比较看看是否是同一个
		System.out.println(p == p2);
		System.out.println("p1.name = " + p.name);
		
	}
}

class Person{
	String name;
	int age;


}

class MyTools{

	// 编写一个方法 copyPerson,可以复制一个 Person 对象,返回复制的对象。克隆对象, 
	// 注意要求得到新对象和原来的 对象是两个独立的对象,只是他们的属性相同
	// 思路
	// 确定返回类型为Person
	// 方法的形参也是 Person p
	// 完成一个复制,创建一个新对象,并复制属性,返回即可
	// 
	// 
	public Person copyPerson(Person p){
		// 创建一个person对象
		Person p2 = new Person();
		p2.name = p.name;
		p2.age = p.age;



		return p2;
	} 
}

递归方法

递归就是方法自己调用自己,每次调用时传入不同的变量.递归有助于编程者解决复杂问题,同时可以让代码变 得简洁

  • 递归入门,递归适合逻辑清晰,能够通过不断迭代来减少问题规模的场景,比如
  • f(n) = f(n-1) + f(n-2)
  • 汉诺塔等

public class Recursion01{
	public static void main(String[] args) {
		
		T t1 = new T();
		t1.test(4);
	}
}

class T{

	public void test(int n){
		if (n > 2){
			test(n-1);
		}

		System.out.println("n=" + n);
	}
}
  • 递归的联系,数据的阶乘

public class Recursion01{
	public static void main(String[] args) {
		
		T t1 = new T();
		// t1.test(4);
		int res = t1.factorial(5);
		System.out.println("res = " + res);	
	}
}

class T{

	public void test(int n){
		if (n > 2){
			test(n-1);
		}

		System.out.println("n=" + n);
	}

	//### factorial 阶乘
	public int factorial(int n){
		if(n == 1){
			return 1;
		}
		return n* factorial(n-1);
	}
}

递归的注意细节

  • 课堂练习1:求出斐波拉列数

public class RecursionEx01{

	public static void main(String[] args) {
		T t1 = new T();

		int res = t1.fibonacci(7);
		System.out.println("当n=7是的斐波那契数:" + res);
	}
}

class T{
	/*
		使用递归的方法求出斐波那契数列,1,1, 2, 3, 5, 8, 13, 给你一个整数n,求它的值是多少?

		思路分析:  
		n = 1  斐波那契是 1	       
		n = 2 斐波那契是 1
		n >= 3 斐波那契是 前面两个数的和
		这里就是递归的思路,n = 7 ,我就需要得到前面两个数,我得到前面两个数,就需要得到前面两个数,直到第一个和第二个数


	 */
	public int fibonacci(int n){
		if(n >= 1){
			if(n == 1 || n == 2){
				return 1;
			}
			else{
				return fibonacci(n-1) + fibonacci(n - 2);
			}
		}
		else{
			System.out.println("输入的数据有误");
			return -1;
		}
		
		
	}
		
}
  • 练习2 猴子吃桃子问题,有一堆桃子,猴子第一天吃了一把,并多吃一个,每天都是这样,当到第10天,只剩下一个桃子,求最初多少个桃子
    这个重点是在在于前一天的桃子 = (后一天的桃子+1) * 2

public class RecursionEx02{
	public static void main(String[] args) {
		
		T t1 = new T();
		int day = 0;
		int peachNum = t1.peach(day);

		System.out.println(day + "的桃子是" + peachNum);

	}
}

class T{

	/*
	猴子吃桃子,每天吃了其中的一半,然后多吃一个,直到第十天,只剩下一个桃子
	请问最初有几个桃子
	思路分析:
	逆推:
	第十天  1个桃子
	第九天 最初 4个 桃子  4/2-1
	第八天 10 个桃子   10/2 -1
	......
	 */
	
	public int peach(int day){
		if(day == 10){
			return 1;
		}
		else if(day >=1  && day <= 9){
			return (peach(day+1) + 1) * 2;
		}
		else{
			System.out.println("day在1-10");
			return -1;
		}


	}
	
	 
}
  • 练习3 老鼠出迷宫问题
    很有意思的一个递归题,对后面数,图的算法理解很有帮助

public class RecursionEx03{


	public static void main(String[] args) {
		// 思路
		// 1.先创建迷宫,用二维数组表示, int[][] map = new int[8][7];
		// 2.先规定map数组的元素:0表示可以走,1表示障碍物
		int[][] map = new int[8][7];

		// 3.将上下两行,左右两列都设置为1
		// 也可以用两个for循环进行设置,更快一点
		
		for(int i = 0; i < map.length; i++){
			for(int j = 0; j < map[i].length; j++){
				if(i == 0 || i == map.length-1){
					map[i][j] = 1;
				}
				else if (j == 0 || j == map[i].length-1){
					map[i][j] = 1;
				}

			}
		}
		// map[2][1] = 1;
		// map[2][2] = 1;
		// map[1][2] = 1;
		map[3][1] = 1;
		map[3][2] = 1;

		// 输出地图情况
		System.out.println("=====地图=======");
		for(int i = 0; i < map.length; i++){
			for(int j=0; j <map[i].length; j++){
				System.out.print(map[i][j] + " ");
			}
			System.out.println();
		}

		// 使用findway找路
		MiGong t1 = new MiGong();
		t1.findWay(map, 1, 1);

		// 输出找路的情况
		System.out.println("\n=====找路的情况=======");
		for(int i = 0; i < map.length; i++){
			for(int j=0; j <map[i].length; j++){
				System.out.print(map[i][j] + " ");
			}
			System.out.println();
		}



	}

}


class MiGong{

	/*
	使用递归回溯的思想来解决老鼠出迷宫
	1. findway专门找到迷宫的路径
	2.找到,就返回true,找不到返回false
	3.map就是二维数组,表示迷宫
	4. i,j就是老鼠的位置,初始化的位置为(1,1),终点位置(6,5);
	5.因为是递归找路,我们规定map数组各个值的含义,
		0:表示可以走,1:表示障碍物,
		2:表示可以走 3:表示走过但是不通
	退出递归:
	6.当走到终点(6,5) = 2 就说明找到通路,就可以退出递归,否则就继续找
	7.先确定老鼠找路的策略 下->右->上->左



	 */
	public boolean findWay(int[][]map, int i, int j){

		if(map[6][5] == 2){ // 说明已经找到
			return true;
		}
		else{
			if(map[i][j] == 0){ // 当前位置为0,表示可以走通
				// 我们假定可以走通
				map[i][j] = 2;
				// 使用找路策略,确定该位置是否真的走通
				if (findWay(map, i+1, j)){
					return true;
				}
				else if(findWay(map, i, j+1)){
					return true;
				}
				else if(findWay(map, i-1, j)){
					return true;
				}
				else if(findWay(map, i, j-1)){
					return true;
				}
				else{
					map[i][j] = 3;
					return false;
				}
			}
			else{ // map[i][j] = 1, 2, 3
				return false;
			}
		}
	} 

}
  • 汉诺塔问题
    汉诺塔问题是递归的经典问题,对于每一个塔来说,只解决三步,
    把最后一个塔以上的所有塔借助第三个针移到第二个针上
    把最后的塔移动第三个针上
    把第二个针上的塔借助第一个针移到第三个针上

public class HanoiTower{
	public static void main(String[] args) {
		
		HanTower tower =  new HanTower();
		tower.move(10, 'A', 'B', 'C');
	}
}


class HanTower{

	// 方法
	// num 表示要移动的个数, a,b,c表示A塔,B塔,C塔
	// 
	// 
	public void move(int num, char a, char b, char c){
		// 如果只有一个盘
		if(num == 1){
			System.out.println(a + "->" + c);
		}
		else{
			// 如果有多个盘,可以 看出两个,最下面的,和上面所有盘
			// 1.先移动上面所有盘到 B, 借助c
			move(num - 1, a, c, b);
			// 2.把最下面的盘移动到c
			System.out.println(a + "->" + c);
			// 再把b塔的所有盘移动到c,借助a
			move(num - 1, b, a, c);
		}

	}
}

方法重载

Java允许在一个类中多个同名的方法存在,但是形不一致,根据形参的数量自动调取需要的方法


public class OverLoad01{
	public static void main(String[] args) {
		
		System.out.println(100);
		System.out.println("hello world");
		System.out.println('h');
		System.out.println(true);
	}
}
  • 自己类中定义的重载

public class OverLoad01{
	public static void main(String[] args) {
		
		// System.out.println(100);
		// System.out.println("hello world");
		// System.out.println('h');
		// System.out.println(true);
		// 
		MyCalculator mc = new MyCalculator();

		System.out.println(mc.calculate(1, 2));
		System.out.println(mc.calculate(1.2, 3.4));
		System.out.println(mc.calculate(1, 2, 3));
	}
}

class MyCalculator{

	// 下面四个方法构成了重载
	// 两个整数的和
	public int calculate(int n1, int n2){
		return n1 + n2;
	}

	public double calculate(int n1, double  n2){
		return n1 + n2;
	}

	public double calculate(double n1, double n2){
		return n1 + n2;
	}

	public int calculate(int n1, int n2, int n3){
		return n1 + n2 + n3;
	}
}
  • 方法重载的注意事项和使用细节
  1. 方法名要一样
  2. 形参必须不一样,比如类型或者数量
  3. 返回值没有要求,返回值类型不同不属于方法重载

public class OverLoadEx01{
	public static void main(String[] args) {
		Methods m1 = new Methods();
		m1.m(3);
		m1.m(3, 4);
		m1.m("hello");

	}
}

class Methods{

	public void m(int a){
		System.out.println(a*a);
	}

	public void m(int a, int b){
		System.out.println(a * b);
	}

	public void m(String s){
		System.out.println(s);
	}
}
  • 练习2,利用重载完成对两个数的比较

public class OverLoadEx02{
	public static void main(String[] args) {
		
		Methods m1 = new Methods();
		System.out.println(m1.max(4, 5));
		System.out.println(m1.max(4.5, 6.7));
		System.out.println(m1.max(7.8, 8.8, 10));
		
		
	}

}

class Methods{

	public int max(int a, int b){
		if(a > b){
			return a;
		}
		else{
			return b;
		}
	}

	public double max(double a, double b){
		if(a > b){
			return a;
		}
		else{
			return b;
		}
	}

	public double max(double a, double b, double c){
		if(a > b){
			if (a > c){
				return a;
			}
			else{
				return c;
			}
		}
		else{
			if(b > c){
				return b;
			}
			else{
				return c;
			}
		}
	}

}

可变参数

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


public class VarParameter02{
	public static void main(String[] args) {
		
		HspMethod m = new HspMethod();
		m.sum();
		System.out.println(m.sum(1, 3, 4));
	}
}


class HspMethod{

	// 计算多个可变参数的值
	// 解读
	// 1. int... 表示接受的可变参数,类型是int,可以接收多个int
	// 2. 使用可变参数时,可以当做数组来使用,即 nums 可以当做数组
	// 3. 遍历求和即可
	// 
	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. 可变参数的实参可以为数组
  2. 实参可以为0个或者多个
  3. 可变参数可以跟普通参数放在新参列表,但是必须保证可变参数放在最后
  4. 一个形参列表中,只能有一个可变参数

public class VarParameterDetail{
	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){
		
	}
}
  • 练习01,利用可变参数完成多个数据的相加

public class VarParameterEx01{
	public static void main(String[] args) {
		
		HspMethod score =  new HspMethod();
		String[] newInfo = score.showScore("jack", 1.2, 3.4, 6.7);

		for(int i = 0; i < newInfo.length; i++){
			System.out.print(newInfo[i] + " ");
		}
	}
}

class HspMethod{

	public String[] showScore(String name, double... scores){

		String[] info = new String[2];
		info[0] = name;

		double sum = 0;
		for(int i = 0; i < scores.length; i++){
			sum += scores[i];
		}
		info[1] = sum + " ";
		return info;
	}
}

作用域


public class VarScope{
	public static void main(String[] args) {
		
		Cat myCat = new Cat();
		myCat.cry();

	}

}

class Cat{
	// 全局变量,也就是属性,作用域在整个Cat类,cry eat 等方法使用属性
	// 
	// 属性定义时,可以直接赋值
	int age = 10;

	// 全局变量可以不赋值,直接使用,因为有默认值
	// 局部变量必须赋值后,才能使用,因为没有默认值
	// 
	double weight; // 默认值是0.0

	public void cry(){
		// 1.局部变量一般是在成员方法中定义的变量
		// 2.这里的n和name都是局部变量
		// 3.n和name的作用域都在cry方法中
		// 
		int n = 10;
		String name = "jack";
		double year;
		System.out.println("在cry中使用属性age = " + age);
		System.out.print(year); // 报错,没有初始化不能使用,但是如果只有变量,但是不使用,也不会报错


	}

	public void eat(){
		System.out.println("在eat中使用属性age = " + age);
	}
	
}
  • 作用域使用细节
  1. 就近原则
  2. 同一个作用域下的变量不能重名
  3. 局部变量的生命周期随着作用域的不同而不同,局部变量的生命周期较短
  4. 不同的方法可以调用

public class VarScopeDetail{

	public static void main(String[] args) {
		Person p1 = new Person();
		p1.say(); //方法结束后,name就销毁了,但是类还在,因此类中的全局变量还存在


		T t1 = new T();
		t1.test();
	}
}

class T{

	// 全局变量,可以在本类中使用,也可以在其他类使用,对象调用
	public void test(){
		Person p2 = new Person();
		p2.say();
		System.out.println(p2.name);
	}
}

class Person{
	String name = "jack";


	public void say(){
		// String name = "king";
		System.out.println("say() name = " + name);
	}
}

构造器

1.构造器没有返回值,也不能写void
2.构造器的名字和类名必须一致
3.构造器形参列表,规则与成员方法一致


public class Constructor{

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

class Person{

	String name;
	int age;
	// 构造器
	// 
	// 1.构造器没有返回值,也不能写void
	// 2.构造器的名字和类名必须一致
	// 3.构造器形参列表,规则与成员方法一致
	public Person(String pName, int pAge){
		System.out.println("构造器被调用~~");
		name = pName;
		age = pAge;
	}
}
  • 构造器的使用细节
  1. 一个类可以有多个构造器,即构造器的重载
  2. 构造器名字必须跟类名一致
  3. 构造器没有返回值
  4. 构造器是完成对象的初始化,不是创建对象
  5. 创建对象时,系统会自动的创建该类的构造方法
  6. 如果程序员没有定义构造 ,系统会自动给类生成一个默认无参构造方法,也叫默认构造方法
  7. 一旦定义了自己的构造器,就覆盖了默认的构造器,就不能使用无参的方法,除非显示的定义一下


public class ConstructorDetail{

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

class Person{

	String name;
	int age;
	// 构造器
	// 
	// 1.构造器没有返回值,也不能写void
	// 2.构造器的名字和类名必须一致
	// 3.构造器形参列表,规则与成员方法一致
	public Person(String pName, int pAge){
		System.out.println("构造器被调用~~");
		name = pName;
		age = pAge;
	}

	public Person(String pName){
		name = pName;
	}
}
  • 练习 ,构造器练习

public class ConstructorEx01{

	public static void main(String[] args) {
		Person p1 = new Person();
		System.out.println("输出所有人:" + p1.age);

		Person p2 = new Person("jack", 199);
		System.out.println("输出" + p2.name + "年龄:" + p2.age);
	}
}

class Person{

	String name;
	int age;

	public Person(){
		age = 18;
	}

	public Person(String pName, int pAge){
		name = pName;
		age = pAge;
	}
}

对象创建的流程分析


this关键字

  • 什么是this?
    java虚拟机会给每个对象分配this,代表当前对象
    使用this解决变量命名问题

public class This01{
	public static void main(String[] args) {
		
		Dog dog1 = new Dog("tom", 12);
		System.out.println("dog1的hashCode=" + dog1.hashCode());
		dog1.info();

		Dog dog2 = new Dog("jack", 6);
		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 就是当前对象的属性
		this.name = name;
		this.age = age;
		System.out.println("this.hashCode=" + this.hashCode());
	}
	

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

}

this 是在创建对象的时候,this的地址与创建对象的地址是一致的
this就是哪个对象调用,就是值哪个对象

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

public class ThisDetail{
	public static void main(String[] args) {
		
		// T t1 = new T();
		// t1.f2();
		T t2 = new T();
		//this
		t2.f1();


	}
}


class T{
	/*
	细节,访问构造器语法,只能在构造器中使用,this(参数列表),且必须放在第一条
	 */
	
	String name = "jack";
	int age = 12;


	public T (){
		
		// 访问这个构造器
		this("jack", 100);
		System.out.println("T() 构造器");
	}

	public T(String name, int age){
		System.out.println("T(String, int) 构造器");
	}
	public void f1(){
		// this("jack", 100);
		String name = "jin";
		System.out.println("f1方法");
		System.out.println("name = " + name  + " age = " + age);
		System.out.println("name = " + this.name  + " age = " + this.age);
	}

	public void f2(){
		System.out.println("f2方法");
		f1();
		this.f1();
	}
}
  • this 课堂练习
    定义 Person 类,里面有 name、age 属性,并提供 compareTo 比较方法,用于判断是否和另一个人相等,提供测试类 TestPerson
    用于测试, 名字和年龄完全一样,就返回 true, 否则返回

public class TestPerson{
	public static void main(String[] args) {
		Person p1 = new Person("小花", 12);
		Person p2 = new Person("小白", 12);

		System.out.println("是否一样" + p2.compareTo(p1));

	}
}

class Person{
	String name;
	int age;

	public Person(String name, int age){
		this.name = name;
		this.age = age;
	}

	public boolean compareTo(Person p1){
		if(this.name.equals(p1.name) && this.age == p1.age){
			return true;
		}
		else{
			return false;
		}
	}

}
  • 类的作业1,返回一个max的方法

public class Homework01{
	public static void main(String[] args) {
		
		A01 a01 = new A01();
		double arr[] = {};
		Double res = a01.max(arr);
		System.out.println("arr的最大值是:" + a01.max(arr));
	}
}


class A01{
	/*
	思路分析:
	1.类名 A01
	2.方法名 max
	3.形参 double[]
	4.返回值 double

	先完成业务,然后在考虑代码的健壮性
	 */
	
	public Double max(double[] arr){
		// 保证arr至少有一个元素
		// 
		if(arr.length > 0){
			double maxNum = arr[0];
			for(int i = 1; i < arr.length; i++){
				if(arr[i] > maxNum){
					maxNum = arr[i];
				}
			}

			return maxNum;
		}
		else{
			return null;
		}
		
	}	

}
  • 作业2:返回字符串数组的元素查找,返回索引

public class Homework02{
	public static void main(String[] args) {
		
		A02 a02 = new A02();

		String[] arr = {"you", "here", "are", "right"};
		System.out.println("返回的索引:" + a02.find(arr, "are"));
	}
}

class A02{

	/*
	思路:
	方法名 find
	形参 字符串数组
	返回值 int

	 */
	public int find(String[] arr, String findThing){
		int findPath = -1;
		for(int i = 0; i < arr.length; i++){
			if(arr[i].equals(findThing)){
				findPath = i;
				break;
			}
		}

		return findPath;

	}
}
  • 作业3,定义一个类,包含书名和价格,可以实现自动对价格进行调整

public class Homework03{
	public static void main(String[] args) {
		
		Book bookPrice = new Book("岁月神偷", 200);
		bookPrice.udpatePrice();
		bookPrice.info();
	}
}

class Book{
	/*
	
	构造一个书类
	实现改变数的价格
	;类型,diuble
	返回值 int

	 */
	String name;
	double price;

	// 构造器
	public Book(String name, double price){
		this.name = name;
		this.price = price;
	}
	
	public void udpatePrice(){
		if(this.price > 150){
			this.price = 150;
		}
		else if(this.price > 100){
			this.price = 100;
		}
		
	}

	// 显示书籍情况
	public void info(){
		System.out.println("书名:" + this.name + " 价格 = " + this.price);
	}
}
  • 作业4: 编写一个类,实现数组的copy功能,输入旧数组,返回一个新数组

public class Homework04{
	public static void main(String[] args) {
	// 方法返回值
	int[] oldArr = {10, 30, 40};
	A03 a3 = new A03();
	int[] newArr = a3.copyArr(oldArr);

	// 遍历
	for(int i = 0; i < newArr.length; i++){
		System.out.print(newArr[i] + "\t");
	}

	}
}

class A03{

	/*
	编写编写一个类,实现数组的copy功能,输入旧数组,返回一个新数组
	实现一个方法,copyArr
	返回一个新数组,元素和就数组一样
	 */
	public int[] copyArr(int[] oldArr){

		int[] newArr = new int[oldArr.length];

		for(int i=0; i < oldArr.length; i++){
			newArr[i] = oldArr[i];
		}

		return newArr;
	}

}
  • 作业5 定义一个圆类,定义属性半径,提供显示圆周长的方法

public class Homework05{
	public static void main(String[] args) {
		Cricle cl = new Cricle(2.5);
		cl.circumference();
		cl.area();

	}
}


class Cricle{
	double radius;

	public Cricle(double radius){
		this.radius = radius;
	}

	// 计算周长
	public void circumference(){
		double circleCum = 2*radius*Math.PI;
		System.out.println("圆的周长为=" + circleCum);
	}

	// 计算面积
	public void area(){
		double circleArea = Math.PI * radius * radius;
		System.out.println("圆的面积为=" + circleArea);
	}

}
  • 作业6 实现一个Cale计算类,输出两个变量表示两个操作数,定义加减乘除

public class Homework06{
	public static void main(String[] args) {
		Cale cale = new Cale(5, 0);
		System.out.println("和=" + cale.add());
		System.out.println("减=" + cale.sub());
		System.out.println("乘=" + cale.mul());
		System.out.println("除=" + cale.div());

	}
}

class Cale{

	double a;
	double b;

	public Cale(double a, double b){
		this.a = a;
		this.b = b;
	}

	public double add(){
		return a + b;
	}

	public double sub(){
		return a - b;
	}

	public double mul(){
		return a * b;
	}

	public Double div(){
		if ( b == 0){
			System.out.println("除数不能为0");
			return null;
		}
		else{
			return a / b;
		}
	}


}
  • 作业7 设计一个Dog类,显示其信息

public class Homework07{
	public static void main(String[] args) {
		Dog bai = new Dog("小白", "白色", 23);
		bai.show();

	}
}

class Dog{
	String name;
	String color;
	int age;

	public Dog(String name, String color, int age){
		this.name = name;
		this.color = color;
		this.age = age;
	}

	public void show(){
		System.out.println("名字:" + name + "颜色" + color + "年龄" + age);
	}

}
  • 作业8 答案是

  • 作业12 复用构造器


public class Homework12{
	public static void main(String[] args) {
		Employee employee = new Employee("小金", "男", 12000);

	}
}

class Employee{
	// 先写少的
	String name;
	String gender;
	int age;
	String position;
	double salary;

	
	public Employee(String name, String gender, int age){
		this.name = name;
		this.gender = gender;
		this.age = age;
	}

	public Employee(String position, double salary){
		this.position = position;
		this.salary = salary;
	}

	public Employee(String name, String gender, int age, String position, double salary){
		// this.name = name;
		// this.gender = gender;
		// this.age = age;
		this(name, gender, age);
		this.position = position;
		this.salary = salary;
	}

}
  • 作业13 类进行调用

public class Homework13{
	public static void main(String[] args) {
		Circle cl = new Circle();
		PassObject ps = new PassObject();
		ps.printAreas(cl, 5);
	}
}

class Circle{
	double radius;

	public double findArea(){
		return radius * radius * Math.PI;
	}

}

class PassObject{

	

	public void printAreas(Circle cl, int times){
		System.out.println("Radius"  + "\t\t" + "Area");

		for(int i = 1;  i <=times; i++){
			cl.radius = i;
			System.out.println(cl.radius + "\t\t" + cl.findArea());
		}
	}

	
}
  • 作业14 电脑和Tom进行猜拳

import java.util.Random;
import java.util.Scanner;

public class Homework14{
	public static void main(String[] args) {
		
		Tom tom = new Tom();
		tom.times = 3;
		int sum = tom.Game();
	}
}

class Tom{

	/*
	思路分析:
	石头 0, 剪刀 1, 布 2

	属性,出一个数
	方法:可以跟电脑猜拳,并显示Tom输赢次数
	 */
	int guessTom;
	int times;

	public int Game(){

		Scanner myScanner =  new Scanner(System.in);
		int count =  0;
		for(int i=0; i< times; i++){
			int guessComputer = (int)(Math.random() * 3);
			System.out.println("请输入Tom的值");
			int guessTom = myScanner.nextInt();
			if(guessTom == guessComputer){
				System.out.println(i + "次平手");
				continue;
			}
			else if (guessTom == 0 && guessComputer == 1 || guessTom == 1 && guessComputer ==2 || guessTom == 2 && guessComputer == 0){
				count+=1;
				System.out.println(i +"次\tTom赢了" + "电脑出的" + guessComputer + "Tom出的" + guessTom);
			}
			else{
				System.out.println(i+ "Tom输了");
			}

		}

		return count;
		


	}
}
posted @ 2021-12-16 22:09  心远志高  阅读(39)  评论(0编辑  收藏  举报