Java笔记之面向对象 上(六)

一、类与对象

1.快速入门

:它是一个抽象的,概念的,代表一类事物,比如人类,猫类…, 即它是数据类型

对象:对象是具体的,实际的,代表一个具体事物, 即 是实例

类和对象的关系:类是对象的模板,对象是类的一个个体,对应一个实例

public class test{
	public static void main(String[] args) {
		new Penson();	//创建了一个人对象
		Penson Penson1 = new Penson();	//把人的对象赋值给Penson1,Penson1就是一个对象

		//对Penson1对象中的属性进行赋值
		Penson1.name = "张三";
		Penson1.age = 20;

		Penson Penson2 = new Penson();	//再创建一个人的对象叫Penson2

		//对Penson2对象中的属性进行赋值
		Penson2.name = "李四";
		Penson2.age = 21;

		//对象属性的访问
		System.out.println("Penson1的属性为:"+ Penson1.name +" "+ Penson1.age);
		System.out.println("Penson2的属性为:"+ Penson2.name +" "+ Penson2.age);
	}
}	

//定义一个人类,其中Penson就是自定义数据类型
class Penson{
	String name;	//姓名
	int age;		//年龄
}

2.属性/成员变量

属性/成员变量:成员变量就是属性,它是类的一个组成部分,一般基本数据类型,或者是引用数据类型(对象、数组等)如:上面定义狗类的 int age 就是属性;

说明:如果属性不赋值则由默认值 比如int的默认值为0

定义格式:访问修饰符 属性类型 属性名;

访问修饰符:就是控制属性的访问范围,一共分为四种分别为 public、proctected、default(默认)、private。

访问权限表

修饰符同一个类同一个包内的类不同包内的子类其他包
public可以可以可以可以
proctected可以可以可以不可以
default可以可以不可以不可以
private可以不可以不可以不可以

3.Java内存结构的分析

JVM内存主要分为三个部分:

  1. 栈:一般存放基本数据类型和局部变量
  2. 堆:存放对象、数组等
  3. 方法区:常量池(常量,比如字符串等)、加载类的信息 如:类的属性、方法等

二、成员方法

1.基本介绍

在某些情况下,我们要需要定义成员方法(简称方法)。比如上面那个人类:除了有一些属性外( 年龄,姓名…),人类还有一 些行为比如:说、计算、睡觉等。这时就要用成员方法才能完成。现在要求对 Person 类完善。

2.定义格式

访问修饰符 返回数据类型 方法名(形参列表…) {
  //方法体 语句;
  return 返回值;
}

  • 访问修饰符:public、proctected、default(默认)、private
  • 返回值类型:void表示没有返回值,int表示返回整形
  • 形参列表:表示用户需要向方法传入的值
public class test{
	public static void main(String[] args) {
		//创建一个对象
		Penson Penson1 = new Penson();

		Penson1.speak();	//调用speak方法
		Penson1.cal(5);		//调用cal方法,并传入一个参数5

		//调用sum方法,并传入两个参数2和3,因为返回值类型是int,所有这里用一个int变量来接收
		int sum1 = Penson1.sum(2,3);	
		System.out.println("2和3的和为:"+sum1);
	}
}	

//定义一个人类,其中Penson就是自定义数据类型
class Penson{
	String name;	//姓名
	int age;		//年龄

	/*
	创建一个名为speak的方法
	方法名:speak
	访问修饰符:public 表示方法是公开的		
	返回值:void	无返回值
	形参列表:() 无形参
	 */
	public void speak(){
		System.out.println("Hello Java");
	}

	/*
	创建一个cal方法,计算1到n之间的累加求和
	方法名:cal
	访问修饰符:public 表示方法是公开的		
	返回值:void	无返回值
	形参列表:(int n)表示需要接受一个整型的参数 
	 */
	public void cal(int n){
		int sum = 0;
		for (int i = 1; i<=n ;i++ ) {
			sum += i;	
		}
		System.out.println("1到"+n+"的和为:"+sum);
	}

	/*
	创建一个sum方法,计算两个数的和
	方法名:sum
	访问修饰符:public 表示方法是公开的		
	返回值:int	int类型的返回值
	形参列表:(int n)表示需要接受一个整型的参数 
	 */
	public int sum(int n,int m){
		int sum1 = n+m;
		return sum1;
	}
}

3.注意事项

1.方法本身

(1)一个方法只能有一个返回值,如果想返回多可以利用数组

public class test{
	public static void main(String[] args) {
		test1 m = new test1();
		int newArr[] = m.getSumAndSub(5,3);
		System.out.println("和为:"+newArr[0]);
		System.out.println("差为:"+newArr[1]);
	}
}	

class test1{
	//返回值为数组类型,可以有多个返回值
	public int[] getSumAndSub(int x,int y){
		//创建一个数组
		int arr[] = new int[2];
		arr[0] = x + y;
		arr[1] = x - y;
		return arr;
	}
}

(2)返回类型可以为任意类型,包含基本类型或引用类型(数组,对象)

(3)如果方法要求有返回数据类型,则方法体中最后的执行语句必须为 return 值; // 而且要求返回值类型必须和 return 的值类型一致或兼容

(4).当方法的返回值为void的时,retrun可以不写,或者只写return

2.参数列表

(1)一个方法可以有0个参数,或者多个参数,中间用逗号隔开

(2)参数的类型可以是基本类型或引用类型

(3)调用带参的方法时,一定对应参数列表传入相应数据类型的值

(4)方法定义时的参数叫形参,调用时的参数叫实参,且对应的类型、个数、顺序以及兼容必须一致。

4.成员方法的传参机制

1.基本数据类型传参

基本数据类型传递的参数,是值的拷贝,形参不会影响实参

public class test{
	public static void main(String[] args) {
		int x = 10;
		int y = 20;
		test1 obj = new test1();
		obj.swap(x,y);
		System.out.println("main中交换后的x和y的值为:"+x+" "+y);  //x=10  y=20
	} 
}	

class test1{
	public void swap(int x,int y){
		System.out.println("swap交换前的x和y的值为:"+x+" "+y);  //x=10  y=20
		//把x和y进行交换
		int temp = x;
		x = y;
		y = temp;
		System.out.println("swap交换后的x和y的值为:"+x+" "+y);  //x=20  y=10
	}
}

2.引用数据类型传参

引用类型传递表面是传递的是值,其实传递的是地址,是可以通过形参影响到实参的

数组为引用

public class test{
	public static void main(String[] args) {
		int arr[] = {1,2,3};
		test1 obj = new test1();
		obj.A(arr);

		//实参会受到影响,随着形参改变而改变
		System.out.println("修改后main方法中遍历数组");
		for (int i=0;i<arr.length;i++ ) {
			System.out.println(arr[i]);		//10 2 3
		}
	} 
}	

class test1{
	public void A(int arr[]){
		System.out.println("修改前A方法中遍历数组");
		for (int i=0;i<arr.length;i++ ) {
			System.out.println(arr[i]);		//1 2 3
		}
		
		//修改数组第一个元素的值
		arr[0] = 10;
		
		System.out.println("修改后A方法中遍历数组");
		for (int i=0;i<arr.length;i++ ) {
			System.out.println(arr[i]);		//10 2 3
		}
	}
}

对象为引用

public class test{
	public static void main(String[] args) {
		test1 t = new test1();
		Person p = new Person();
		p.name = "zhangsan";
		p.age = 18;

		//调用方法A
		t.A(p);
		System.out.println(p.age);	//20

		//调用方法B,其值不会发生改变,因为B方法中的p和main方法中的p不是同一个对象,内存地址也不一样,
		t.B(p);	
		System.out.println(p.age);	//值不变依然是20
	} 
}	

class Person{
	String name;
	int age;
}

class test1{
	public void A(Person p){
		p.age = 20;
	}

	public void B(Person p){
		p = new Person();
		p.age = 30;
	}
}

5.对象的克隆

将一个对象的属性copy到另一个对象中去

public class test{
	public static void main(String[] args) {
		Person p = new Person();
		p.name = "zhangsan";
		p.age = 20;

		test1 t = new test1();
		Person p1 = t.copyPerson(p);

		//p和p1是两个不同的对象,但是属性值时一样的,这就完成对象的copy
		System.out.println("p的name和age为:"+p.name+" "+p.age);
		System.out.println("p的name和age为:"+p1.name+" "+p1.age);
	}
}

class Person{
	String name;
	int age;
}

class test1{
	//创建一个返回值为Person的对象
	public Person copyPerson(Person p){
		Person p1 = new Person();
		p1.name = p.name;
		p1.age = p.age;
		return p1;
	}
}

三、方法的递归调用

1.基本介绍

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

阶乘问题


public class test{
	public static void main(String[] args) {
		//普通方法求阶乘
		int s = 1;
		for (int i = 1; i<=5 ; i++ ) {
			s *= i;
		}
		System.out.println("5的阶乘为:"+s);

		//递归方法
		test1 obj = new test1();
		int x = obj.jc(5);
		System.out.println("5的阶乘为:"+x);
	}
}

class test1{
	public int jc(int x){
		if (x == 1) {
			return 1;
		}else{
			return jc(x-1)*x;
		}
	} 
}

2.注意事项

  • 递归必须有退出条件,否则就会出现无限递归调用,就会死归
  • 如果方法中使用引用类型变量(比如数组,对象等),就会共享该引用类型的数据
  • 方法中的局部变量是独立的,不会相互影响
  • 当一个方法执行完毕时,或者遇到return,这个方法就执行完毕,并且返回

3.使用递归解决经典问题

斐波那契数列问题

public class test{
	public static void main(String[] args) {
		//递归方法
		test1 obj = new test1();
		int x = obj.A(7);
		System.out.println("斐波那契数列的第七项为:"+x);	//值为13
	}
}

class test1{
	public int A(int x){
		if (x>=1) {
			if ( x == 1 || x == 2) {
				return 1;
			}else{
				return A(x-1)+A(x-2);
			}	
		}else{
			System.out.println("请输入一个>=1的数");
			return -1;
		}
	} 
}

猴子吃桃子问题

假如有一堆桃子,第一天猴子吃了其中的一半,并再多吃一个,以后每天猴子都吃其中的一半,并再多吃一个,当第10天时,发现只有1个桃子了,问在第5天时还有多少个桃子

public class test{
	public static void main(String[] args) {
		/*
		进行一个 逆推
		第10天:1个桃子
		第9天:4个桃子
		第8天:10个桃子
		第n天 = (n+1的桃子+1)*2
		 */
		test1 obj = new test1();
		int x = obj.A(8);
		System.out.println("第五天的桃子为:"+x);
	}
}

class test1{
	public int A(int x){
		if (x == 10) {
			return 1;
		}else if(x>=1 || x<=9){
			return (A(x+1)+1)*2;
		}else{
			System.out.println("请输入1-10之内的天数");
			return -1;
		}
	} 
}

老鼠出迷宫问题

public class test{
	public static void main(String[] args) {
		/*
		第一步:创建一个长8宽8的迷宫,使用二维数组并赋值,0表示可通,1表示不通
		1 1 1 1 1 1 1 1
		1 0 0 0 0 0 0 1 
		1 0 0 0 0 0 0 1
		1 1 1 1 1 0 0 1
		1 0 0 0 0 0 0 1
		1 0 0 0 0 0 0 1
		1 0 0 0 0 0 0 1
		1 1 1 1 1 1 1 1
		 */
		int arr[][] = new int[8][8];
		for (int i = 0; i<8 ; i++) {
			for (int j = 0 ; j<8 ; j++ ) {
				if (i == 0 || i == 7) {
					arr[i][j] = 1;
				}
			}
		}

		for (int i = 0; i<8 ; i++) {
			for (int j = 0 ; j<8 ; j++ ) {
				if (j == 0 || j == 7) {
					arr[i][j] = 1;
				}
			}
		}

		arr[3][1] = 1;
		arr[3][2] = 1;
		arr[3][3] = 1;
		arr[3][4] = 1;

		//二维数组的遍历
		for (int i = 0; i<8 ; i++) {
			for (int j = 0 ; j<8 ; j++ ) {
				System.out.print(arr[i][j]+" ");
			}
			System.out.println();
		}


		//创建findWay对象,开始找路
		test1 t =  new test1();
		boolean f =  t.findWay(arr,1,1);

		System.out.println("======小老鼠找到出口路径======");
		for (int i = 0; i<8 ; i++) {
			for (int j = 0 ; j<8 ; j++ ) {
				System.out.print(arr[i][j]+" ");
			}
			System.out.println();
		}
		/*
		1 1 1 1 1 1 1 1
		1 2 0 0 0 0 0 1
		1 2 2 2 2 2 0 1
		1 1 1 1 1 2 0 1
		1 0 0 0 0 2 0 1
		1 0 0 0 0 2 0 1
		1 0 0 0 0 2 2 1
		1 1 1 1 1 1 1 1
		*/
	}
}


/*
1.小老鼠初始位置是不确定的,出口的位置为arr[6][5]
2.如果找到出口返回true,否则返回false
3.其中数组元素为0表示可通,1表示不通,2表示小老鼠顺利到出口的路径,3表示走过但是没有走通
4.当arr[6][5] = 2时,则说明找到出口结束,否则继续找
5.确定老师找路的方法:首先从下开始走,如果下面走不通,就往右走,依次顺序为下->右->上->左
 */
class test1{
	public boolean findWay(int arr[][],int i,int j){
		if (arr[6][6] == 2) {
			return	true;
		}else{
			if (arr[i][j] == 0) {	//等于0说明可以走
				//假设可以走我就设置当前数组元素为2
				arr[i][j] = 2;
				//通过找路的方法进行判断是否可以走通
				if (findWay(arr,i+1,j)) {	//往下走
					return true;
				}else if (findWay(arr,i,j+1)) {	//右	
					return true;
				}else if (findWay(arr,i-1,j)) {	//上
					return true;
				}else if (findWay(arr,i,j-1)) {	//左
					return true;
				}else {
					//如果上下左右都走不通则说明当前位置为死路,也就是小老鼠走不出迷宫
					arr[i][j] = 3;
					return false;
				}
			}else{
				return false;
			}
		}
	} 
}

汉诺塔问题

将下图A塔中所有的盘子,搬运到B塔或者C塔中

要求:
1.每次只能搬运一个盘子
2.最终搬完以后的顺序和A塔的顺序一样

在这里插入图片描述

public class test{
	public static void main(String[] args) {
		test1 t = new test1();
		t.move(3,'a','b','c');
	}
}


class test1{
	//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 {
			//如果有多个盘子,使用递归调用进行搬运
			//先移动A塔上面所有的盘子到B塔,需要借助C塔
			move( num-1,a,c,b);
			System.out.println(a + "塔 到 " + b + "塔");
			//再把B塔上面所有的盘子到C塔,需要借助A塔
			move( num-1,b,a,c);
		}
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

王博1999

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

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

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

打赏作者

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

抵扣说明:

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

余额充值