第七章 面向对象编程(基础)
1. 类与成员方法
类与对象关系示意图
- 示例:代码
import java.util.Scanner;public class IntDetail{public static void main(String[] args){Cat cat1=new Cat();cat1.name="小花";cat1.age=12;cat1.color="白";Cat cat2=new Cat();cat2.name="小蓝";cat2.age=100;cat2.color="蓝";System.out.println("第一只猫颜色:"+" "+cat1.name+" "+cat1.age+" "+cat1.color+" "+"第二只猫颜色:"+" "+cat2.name+" "+cat2.age+" "+cat2.color); }
}
class Cat{String name;int age;String color;
}
类与对象的区别和联系:
- 类是抽象的,概念的,代表一类事物,比如人类,猫类… 即它是数据类型。
- 对象是具体的,实际的,代表一个具体事物,即 是实例。
- 类是对象的模板,对象是类的一个个体,对应一个实例。
对象在内存中的存在形式:
属性使用注意细节:
- 属性的定义语法同变量,示例:访问修饰符 属性类型 属性名;这里老师简单的介绍访问修饰符: 控制属性的访问范围。有四种访问修饰符 public,proctected,默认,private ,后面我会详细介绍。
- 属性的定义类型可以为任意类型,包含基本类型或引用类型。
- 属性如果不赋值,有默认值,规则和数组一致。具体说:
int 0,short 0,byte 0, long 0, float 0.0,double 0.0, char \u0000, boolean false,String null。
思考题:
内存图:
类和对象的内存分配机制
Java内存的结构分析
- 栈: 一般存放基本数据类型(局部变量)
- 堆: 存放对象(Cat cat,数组等)
- 方法区:常量池(常量,比如字符串),类加载信息
示例:
练习题:
答案:
小明✅
0❌正确答案:200
0❌正确答案:会抛出异常
分析图:
2. 成员方法🚩
成员方法快速入门:
- 代码
import java.util.Scanner;public class IntDetail{public static void main(String[] args){Person peraon1=new Person();peraon1.speak();System.out.println();peraon1.cal01();Scanner myScanner=new Scanner(System.in);System.out.println("请输入一个整数n:");int n=myScanner.nextInt();peraon1.cal02(n);System.out.println("请输入一个整数n1:");int n1=myScanner.nextInt();System.out.println("请输入一个整数n2:");int n2=myScanner.nextInt();int sum=peraon1.getSum(n1,n2);System.out.println(n1+"+"+n2+"的结果是:"+sum); }
}
class Person{String name;int age;//1.public 表示方法是公开
//2.void :表示方法没有返回值
//3.speak():speak是方法名,()形参列表
//4.{}方法体,可以写我们要执行的代码
//5.System.out.println("我是一个好人”);表示我们的方法就是输出一句话public void speak(){System.out.println("我是一个好人");}public void cal01(){int sum=0;for(int i=1;i<=1000;i++){sum+=i;}System.out.println("1+...+1000的结果是:"+sum);}public void cal02(int n){int sum=0;for(int i=1;i<=n;i++){sum+=i;}System.out.println("从1+...+"+n+"的结果是:"+sum);}public int getSum(int n1,int n2){int sum=n1+n2;return sum;}}
输出结果:
方法的调用机制:❗
示例:多次输出数组
import java.util.Scanner;public class IntDetail{public static void main(String[] args){int[][] arr={{0,0,1},{1,1,1,},{1,1,3}};MyTools myTool=new MyTools();myTool.printArr(arr);myTool.printArr(arr);myTool.printArr(arr);}
}class MyTools{public void printArr(int[][] map){System.out.println("=================");for(int i=0;i<map.length;i++){for(int j=0;j<map[0].length;j++){System.out.print(map[i][j]+" ");}System.out.println();} }
}
输出结果:
方法使用细节1.
成员方法使用细节2
方法不能嵌套定义❗❗
成员方法使用细节3
同一个类中的方法调用:直接调用即可。
跨类中的方法A类调用B类方法:需要通过对象名调用。
练习题:
- 第一题代码:
import java.util.Scanner;public class IntDetail{public static void main(String[] args){int n=23;AA a=new AA();if(a.isOdd(n)){System.out.println(n+"是奇数");}else{System.out.println(n+"是偶数");} }
}class AA{public boolean isOdd(int n){// if(n%2==1){// return true;// }else{// return false;// }return n%2!=0;}
}
- 第二题代码:
import java.util.Scanner;public class IntDetail{public static void main(String[] args){int n=4;int m=3;char ch='#';printchar p=new printchar();p.prichar(n,m,ch);}
}
class printchar{public void prichar(int n,int m,char ch){for(int i=0;i<n;i++){for(int j=0;j<m;j++){System.out.print(ch+" ");}System.out.println();}}
}
运行结果:
3. 成员方法传参机制🚩
基本数据类型传参机制:
结论: 基本数据类型,传递的是值(值拷贝),形参的任何改变不影响实参❗❗❗
引用数据类型传参机制:
- 代码:
import java.util.Scanner;public class IntDetail{public static void main(String[] args){//!!!数组是引用类型!!!int[] arr={1,2,3};BB b=new BB();b.test100(arr);System.out.println("=mian===========");for(int i=0;i<arr.length;i++){System.out.print(arr[i]+" ");//200 2 3}}
}
class BB{public void test100(int[] arr){arr[0]=200;for(int i=0;i<arr.length;i++){System.out.print(arr[i]+" ");//200 2 3}System.out.println();}}
结论: 引用类型传递的是地址(传递也是值,但是值是地址),可以通过形参影响实参❗❗❗
克隆对象
- 代码:将p1克隆给p2,但不是同一个对象,是两个独立的空间。
import java.util.Scanner;public class IntDetail{public static void main(String[] args){Person p1=new Person();p1.name="小明";p1.age=20;MyTools myTool=new MyTools();Person p2=myTool.copyPerson(p1);System.out.println("p2的信息:"+p2.name+" "+p2.age);//可以同对象比较看看是否为同一个。System.out.println(p1==p2);//false}
}
class Person{String name;int age;}
class MyTools{public Person copyPerson(Person p){Person p2=new Person();p2.name=p.name;p2.age=p.age;return p2;}}
递归能解决什么问题?
递归执行机制:举例1:打印问题
举例2:阶乘问题
递归重要规则:
- 执行一个方法时,就创建一个新的受保护的独立空间(栈空间)
- 方法的局部变量是独立的,不会相互影响,比如n变量
- 如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据。
- 递归必须向退出递归的条件逼近,否则就是无限递归,出现StackOverflowError,死龟了:)
- 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行
完毕。
练习1:
请使用递归的方式求出斐波那契数1,1,2,3,5,8,13…给你一个整数n,求出第n个斐波那契数是多少?
import java.util.Scanner;public class IntDetail{public static void main(String[] args){Fibo f=new Fibo();int n=7;System.out.println("当n="+n+"对应的斐波那契数="+ f.fibonacci(7));}
}
class Fibo{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:猴子吃桃子问题
思路:
- 代码:
import java.util.Scanner;public class IntDetail{public static void main(String[] args){Taozi t1=new Taozi();int day=9;int peachNum=t1.peach(day);if(peachNum!=-1){System.out.println("第"+day+"天有"+ peachNum+"个桃子");}}
}class Taozi{public int peach(int day){if(day==10){return 1; }else if(day>=1&&day<=9){return (peach(day+1)+1)*2;}else{return -1;}}
}
迷宫问题
分析:
- findway方法就是专内来找出迷宫的路径。
- 如果找到,就返回 true,否则返回false。
- map 就是二维数组,即表示迷宫。
- i,j 就是老鼠的位置,初始化的位置为(1,1)。
- 因为是递归的找路,所以我先规定 map数组的各个值的含义:0 表示可以走 ,1 表示障碍物 ,2 表示可以走 ,3 表示走过,但是走不通是死路。
- 当map[6][5]=2 就说明找到通路,就可以结束,否则就继续找。
- 先确定老鼠找路策略 下->右->上->左
- 代码
public class IntDetail{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 j=0;j<map[0].length;j++){map[0][j]=1;map[7][j]=1;}map[3][1]=1;map[3][2]=1;map[3][4]=1;map[4][3]=1;//输出当前地图System.out.println("=====当前地图情况=====");for(int i=0;i<map.length;i++){for(int j=0;j<map[0].length;j++){System.out.print(map[i][j]+" ");}System.out.println();}T t1=new T();t1.findWay(map,1,1);System.out.println("\n=====找路情况如下=====");for(int i=0;i<map.length;i++){for(int j=0;j<map[0].length;j++){System.out.print(map[i][j]+" ");}System.out.println();}}
}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)){//下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{return false;}}}
}
输出结果:
修改找路策略:
先走上-右-下-左
结果:
汉诺塔
写代码的时候就按照只有两个盘的移动顺序写。
- 代码
//最终移动到c盘
public class IntDetail{public static void main(String[] args){int num=2;char a='a';char b='b';char c='c';Tower tower=new Tower();tower.move(num,a,b,c);}
}class Tower{public void move(int num,char a,char b,char c){if(num==1){System.out.println(a+"->"+c);}else{//(1)移动上面所有盘到b,借助cmove(num-1,a,c,b);//(2)把下面的盘移动到cSystem.out.println(a+"->"+c);//(3)把b塔所有的盘,移动到c,借助amove(num-1,b,a,c);}}
}
输出结果:
八皇后:回溯算法的典型案例
4. overload(重载)
基本介绍
代码示例:
案例:
代码:
注意事项和使用细节:
练习题1:
答案:c、e、g❌
正确答案:
b、c、d、e
练习题2:
练习题3:
5. 可变参数
基本概念:
基本语法:
示例:
输出结果:
可变参数的注意事项和使用细节:
练习题1:
6. 作用域
局部变量一般是指在成员方法中定义的变量。
全局变量:也就是属性,作用域为整个类体。
局部变量:也就是除了属性之外的其他变量,作用域为定义它的代码块中!
全局变量(属性)可以不赋值,直接使用,因为有默认值,局部变量必须赋值后才能使用,因为没有默认值。
7. 构造器🚩
8. this
作业