一、类和对象
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的随机数。