韩顺平Java-第七章:面向对象编程(基础)

一、类和对象

1、定义及区别

​ (1)类是抽象的,概念的,代表一类事物,比如人类,猫类…,即它是数据类型;

​ (2)对象是具体的,实际的,代表一个具体事物,即它是实例;

​ (3)类是对象的模板,对象是类的一个个体,对应一个实例。

2、对象内存布局

在这里插入图片描述

3、属性/成员变量
(1)基本介绍

​ ① 从概念或者叫法上看:成员变量 = 属性 = field(字段)即成员变量是用来表示属性的;

​ ② 属性是类的一个组成部分,一般是基本数据类型,也可以是引用类型(对象,数组)。

(2)注意事项和细节说明

​ ① 属性的定义语法同变量;

​ ② 属性的定义类型可以为任意类型,包括基本类型和引用类型;

​ ③ 属性如果不赋值,有默认值,规则和数组一致。

(3)访问属性

​ 对象名.属性名;

4、对象
(1)创建对象

​ ① 先声明再创建

​ Cat cat;

​ cat = new Cat();

​ ② 直接创建

​ Cat cat = new Cat();

(2)对象分配机制

在这里插入图片描述

在这里插入图片描述

(3)Java创建对象的流程简单分析

​ ① 先在方法区中加载Person类信息(属性和方法信息,只会加载一次,之后用该类创建对象就不用加载了。);

​ ② 在堆中分配空间,进行默认初始化(看规则);

​ ③ 把地址赋给p,p就指向对象;

​ ④ 进行指定初始化,比如 p.name = “jack” p.age = 10。

5、成员方法
(1)方法的定义

​ 访问修饰符 返回数据类型 方法名(形参列表…){ //方法体

​ 语句;

​ return 返回值;

​ }

​ ① 参数列表:表示成员方法输入;例如 cal (int n) ,getSum(int num1,int num2)

​ ② 返回数据类型:表示成员方法输出,void表示没有返回值;

​ ③ 方法主体:表示为了实现某一功能代码块;

​ ④ 访问修饰符:作用是控制方法使用的范围

​ ⑤ return语句不是必须的。

(2)方法调用机制

​ 分析的代码:

在这里插入图片描述

在这里插入图片描述

​ 分析的步骤:

在这里插入图片描述

​ 分析的小结:

在这里插入图片描述

(3)方法的使用细节

​ ① 访问修饰符

​ 作用是控制方法使用的范围,有四种:public,protected,默认,private。如果不写就是默认访问修饰符。

​ ② 返回数据类型

​ a. 一个方法最多有一个返回值。如果返回多个结果,就要用到数组;

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

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

​ d. 如果方法是void,则方法体中可以没有return语句,或者只写return。

​ ③ 方法名

​ 遵循驼峰命名法,最好见名知意,表达出该功能的意思即可。

​ ④ 形参列表

​ a. 一个方法可以有0个参数,也可以有多个参数,中间用逗号隔开,比如:getSum(int n1,int n2)。

​ b. 参数类型可以为任意类型,包含基本类型或引用类型,比如:printArr(int[][] map)。

​ c. 调用带参数的方法时,一定对应着参数列表传入相同类型或兼容类型的参数!

​ d. 方法定义时的参数成为形式参数,简称形参;方法调用时的传入参数称为实际参数,简称实参,实参和形参的类型要一致或者兼容、个数、顺序必须一致!

​ ⑤ 方法体

​ 里面写完成功能的具体的语句,可以为输入、输出、变量、运算、分支、循环、方法调用,但里面不能再定义方法!即方法不能嵌套定义。

​ ⑥ 方法调用细节说明

​ a. 同一个类中的方法调回用:直接调用即可。

​ b. 跨类中的方法A调用B类方法:需要通过对象名调用。

​ c. 跨类的方法调用和方法的访问修饰符相关。

(4)方法的传参机制

​ ① 基本数据类型,传递的是值(值拷贝),形参的任何改变不影响实参;

​ ② 引用类型传递的是地址(传递也是值,但是值是地址),可以通过形参影响实参;

​ ③ 若是对象,则变得不同,因为对象传的是地址。

二、递归

1、递归调用机制

​ 执行代码:

在这里插入图片描述

在这里插入图片描述

​ 执行过程:

在这里插入图片描述

​ 执行结果:

在这里插入图片描述

2、递归重要规则

​ (1)执行一个方法时,就创建一个新的受保护的独立空间(栈空间);

​ (2)方法的局部变量是独立的,不会相互影响,比如n变量;

​ (3)如果方法中使用的是引用类型变量(比如数组,对象),就会共享该引用类型的是数据;

​ (4)递归必须向退出递归的条件逼近,否则就是无限递归,出现StackOverflowError;

​ (5)当一个方法执行完毕,或则遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者让返回时,该方法也就执行完毕了。

3、递归实例
(1)斐波那契序列
// 斐波那契额数:1,1,2,3,5,8,13....
class T{
	public int feiBo(int n){
		if (n < 3) {
			return 1;
		}else{
			return feiBo(n - 1) + feiBo(n - 2);
		}
	}
}
(2)猴子吃桃
//有一堆桃子,猴子第一天吃了其中的一半,并且多吃了一个,以后每天猴子都吃其中的一般,
//然后多吃一个。当到第十天的时候,还没吃呢,发现只有一个桃子了,求最初共有几个桃子。
//返回的是第n天的桃子数。
class T{
	public int leiJia(int n){
​		if (n == 10) {
​			return 1;
​		}else{
​			return 2 * (leiJia(n + 1) + 1); 
​		}		
	}
}
(3)迷宫问题

在这里插入图片描述

public class MiGong01{
	public static void main(String[] args) {

​		//制作地图
​		int[][] map = new int[8][7];
​		for (int i = 0;i < map.length;i++) {
​			map[i][0] = 1;
​			map[i][6] = 1;
​		}
​		for (int i = 0;i < 7;i++) {
​			map[0][i] = 1;
​			map[7][i] = 1;
​		}
​		map[3][0] = 1;
​		map[3][1] = 1;
​		map[3][2] = 1;
​		map[2][2] = 1;
​		//打印地图
​		for (int i = 0;i < map.length;i++) {
​			for (int j = 0;j <map[j].length;j++) {
​				System.out.print(map[i][j] + " ");
​			}
​			System.out.println();
​		}
​		T t =new T();
​		t.findWay(map,1,1);
​		System.out.println("走过后的地图===========");
​		//打印地图
​		for (int i = 0;i < map.length;i++) {
​			for (int j = 0;j <map[j].length;j++) {
​				System.out.print(map[i][j] + " ");
​			}
​			System.out.println();
​		}
	}
}

//设定 0:未走 1:障碍物 2:可走 3:不可走(走过,死胡同)
//下→右→上→左顺序走迷宫
class T{
	public boolean findWay(int[][] map,int i ,int j){
		if (map[6][5] == 2) {//说明以及到终点
			return true;
		}else{
			if (map[i][j] == 0) {//未走
				map[i][j] = 2;//假设可以走
				if (findWay(map,i + 1,j)) { //如果能走通,返回true
					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{//走不通,标记3,返回false
					map[i][j] = 3;
					return false;
				}
			}else{// 1,2,3种情况不需要走了
				return false;
			}
		}
	}
}
(4)、汉诺塔
public class HanNuoTa{
	public static void main(String[] args) {
		T t = new T();
		t.move(3,'a','b','c');
	}
}
class T{//num 表示盘子个数,a,b,c表示串子
	public void move(int num , char a,char b,char c){
		if (num == 1) {//只有一个盘子,直接a->c,不需要借助b
			System.out.println(a +"->"+c);
		}else{//有两个以上的盘子,把盘子视为上面的盘子和下面的一个盘子
			//(1)先移动上面的盘子,从a->b,借助c
			move(num - 1,a,c,b);
			//(2)再移动下面的一个盘子,从a->c
			System.out.println(a + "->" + c);
			//(3)最后移动在b的盘子,从b->c,借助a
			move(num - 1,b,a,c);
		}
	}
}
(5)、八皇后

​ 暂未解决

三、方法重载(overload)

1、基本介绍

​ java种允许同一个类中,多个同名方法的存在,但要求形参列表不一致!

​ 比如:System.out.println();out是PrintStream类型。

2、重载的好处

​ (1)减轻了起名的麻烦;

​ (2)减轻了记名的麻烦。

3、注意事项和使用细节

​ (1)方法名:必须相同;

​ (2)参数列表:必须不同(形参类型或个数或顺序,至少有一样不同,参数名无要求);

​ (3)返回类型:无要求。

四、可变参数

1、基本概念

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

2、基本语法

​ 访问修饰符 返回类型 方法名(数据类型… 形参名){

​ }

3、注意事项和使用细节

​ (1)可变参数的实参可以为0个或者任意多个;

​ (2)可变参数的实参可以为数组;

​ (3)可变参数的本质就是数组;

​ (4)可变参数可以和普通类型的参数一起放在形参列表,但是必须保证可变参数在最后;

​ (5)一个形参列表中只能出现一个可变参数。

五、作用域

1、基本介绍

​ (1)在java编程中,主要的变量就是属性(成员变量)和局部变量;

​ (2)局部变量一般是指在成员方法中定义的变量;

​ (3)java中作用域的分类:

​ ① 全局变量:也就是属性,作用域为整个类体;

​ ② 局部变量:也就是除了属性之后的其他变量,作用域为定义它的代码块中。

​ (4)全局变量(属性)可以不复制,直接使用,因为有默认值,局部变量必须赋值后,才能使用,因为没有默认值。

2、注意事项和细节使用

​ (1)属性和局部变量可以重名,访问时遵循就近原则;

​ (2)在同一个作用域中,比如在同一个成员方法中,两个局部变量,不能重名;

​ (3)属性生命周期较长,伴随着对象的创建而创建,伴随着对象的死亡而死亡 。局部变量,生命周期较短,伴随着它的代码块的执行而创建,伴随着代码块的结束而死亡。即在一次方法调用过程中。

​ (4)作用域范围不同:

​ ① 全局变量:可以被本类使用,或者他类使用(通过对象调用);

​ ② 局部变量:只能在本类中对应的方法中使用。

​ (5)修饰符不同

​ 全局变量/属性可以加修饰符(public、protected、private),局部变量不可以加修饰符。

六、构造方法\构造器

1、基本介绍

​ 构造方法又称构造器(constructor),是类的一种特殊的方法,它的主要作用是完成对新对象的初始化,有几个特点:

​ (1)方法名和类名相同;

​ (2)没有返回值;

​ (3)在创建对象时,系统会自动的调用该类的构造器完成对象的初始化(注意对象是已经存在的)。

2、基本语法

​ [修饰符] 方法名(形参列表){

​ 方法体;

​ }

​ (1)构造器的修饰符可以默认,也可以是public、protected、private;

​ (2)构造器没有返回值,也不能写void;

​ (3)方法名和类名字必须一样;

​ (4)参数列表和成员方法的参数列表一样的规则;

​ (5)构造器的调用由系统完成。

3、注意事项和使用细节

​ (1)一个类可以定义多个不同的构造器,即构造器重载;

​ 比如:我们可以给Person类定义一个构造器,用来创建对象的时候,只指定人名,不需要指定年龄。

​ (2)构造器名和类名要相同;

​ (3)构造器没有返回值;

​ (4)构造器是完成对象的初始化,并不是创建对象;

​ (5)在创建对象时,系统自动的调用该类的构造方法;

​ (6)如果程序员没有定义构造器,系统会自动给类生成一个默认无参构造器(也叫默认构造器)。可以使用javap指令 反编译查看;

​ (7)一旦定义了自己的构造器,默认的构造器就覆盖了,就不能再使用默认的无参构造器,除法显示的定义一下,即类名 (){ }。

七、对象创建的流程分析

在这里插入图片描述

​ (1)首先加载Person类信息(Person.class),只会加载一次;

​ (2)在堆中分配空间(地址);

​ (3)完成对象的初始化;

​ ① 默认初始化 age = 0,name = null;

​ ② 显式初始化 age = 90,name = null;

​ ③ 构造器的初始化 age = 20,name = 小倩;

​ (4)对象在堆中的地址返回给p(p是对象名,也可以理解为对象的引用)。

八、this关键字

1、this的理解

在这里插入图片描述

在这里插入图片描述

​ 哪个对象调用,this就代表哪个对象。

2、注意事项和使用细节

​ (1)this关键字可以用来访问本类的属性、方法、构造器;

​ (2)this用于区分当前类的属性和局部变量;

​ (3)访问成员方法的语法:this.方法名(参数列表);

​ (4)访问构造器语法:this(参数列表);注意只能在构造器中使用(即只能在构造器中访问另外一个构造器,并且该语句必须放在第一条语句)

​ (5)this不能再类定义的外部使用,只能在类定义的方法中使用。

知识点

1、Java内存的结构分析

​ (1)栈:一般存放基本数据类型(局部变量);

​ (2)堆:存放对象(Cat cat,数组等);

​ (3)方法区:常量池(常量,比如字符串),类加载信息。

2、圆周率的使用

​ 语法:Math.PI

3、Double类

​ Double是java定义的类,而double是预定义数据类型(8种中的一种),Double是类所以其对象是可以为NULL的,而double定义的不能为NULL。

4、匿名对象
public class Test{ //共有类
    int count = 9; //属性
    public void count1(){ //Test类下的成员方法
        count = 10;
        System.out.println("count1=" + count); //10    
    }
    public void count2(){
        System.out.println("count1=" + count++);
    }

	//这是Test类的main方法,任何一个类,都可有main
	public static void main(String args[]){
		// 1. new Test()是匿名对象,匿名对象使用后,就不能用了
		// 2. new Test().count1() 创建好匿名对象后,就调用count1()
		new Test().count1(); // 10

		Test t1 = new Test();
		t1.count2(); // 9 因为count++先输出,再自增
		t1.count2(); // 10 同上
	}
}
5、输出0-2的随机数

对象名.nextInt(3) //输出0-2的随机数。

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值