概述
第5章 程序控制结构
5.1 五种控制结构
-
if-else
if(age>18){ System.out.println(" "); } else { System.out.println(" "); }
-
switch
switch(c1) { case 'a' : System.out.println("A"); break; case 'b' : System.out.println("B"); break; case 'c' : case 'd' : case 'e' : System.out.println("C,D,E"); break; default : System.out.println("你的输入有误~")
-
for
for(int i= 0 , j = 0; i<100; i++,j++;){ System.out.println("i=" + i +"j="+ j); }
-
while
- while 循环也有四要素
- 只是四要素放的位置和for比一样
while(i<=10){ System.out.println(" "); i++; }
-
do…while
循环变量初始化;
do{
循环体(语句);
循环变量迭代;
}while(循环条件);
do{ System.out.println( ); i++; }while(i<=10);
-
5.2 switch 注意事项
例题
- 对学生成绩大于 60 分的,输出"合格"。低于 60 分的,输出"不合格"。(注:输入的成绩不能大于 100), 提示 成绩/60*
提示
这里我们需要进行一个转换, 编程思路 :
如果成绩在 [60,100] , (int)(成绩/60) = 1
如果成绩在 [0,60) , (int)(成绩/60) = 0
if( score >= 0 && score <= 100) {
switch ((int)(score / 60)) {
case 0 :
System.out.println("不合格");
break;
case 1 :
System.out.println("合格");
break;
// default :
// System.out.println("输入有误");
}
} else {
System.out.println("输入的成绩在 0-100");
}
switch 和 if 的比较
- 如果判断的具体数值不多,而且符合 byte、 short 、int、 char, enum[枚举], String 这 6 种类型。虽然两个语句都可 以使用,建议使用 swtich 语句。
- 其他情况:对区间判断,对结果为 boolean 类型判断,使用 if,if 的使用范围更广
5.3 for 注意事项
- 循环条件是返回一个布尔值的表达式
- for(;循环判断条件;) 中的初始化和变量迭代可以写到其它地方,但是两边的分号不能省略。
- 循环初始值可以有多条初始化语句,但要求类型一样,并且中间用逗号隔开,循环变量迭代也可以有多条变量迭代 语句,中间用逗号隔开。
###5.83 while 注意事项
- 循环条件是返回一个布尔值的表达式
- while 循环是先判断再执行语句
5.4 do…while
- 先执行,再判断,也就是说,一定会至少执行一次
- 最后 有一个 分号 ;
- while 和 do…while 区别举例: 要账
5.5 多重循环控制
-
设外层循环次数为 m 次,内层为 n 次,则内层循环体实际上需要执行 m*n 次。
-
九九乘法表
public class Test { /** * java实现九九乘法 */ public static void main(String[] args) { //九九乘法 for(int i = 1;i <= 9;i++){ for(int j = 1;j <= i;j++){ System.out.print(j+"*"+ i +"="+i*j+" ");//此处用的print } System.out.println(); } }
5.6经典的打印的金字塔
- 矩形
*****
*****
*****
*****
*****
for(int i = 1;i <=5;i++){
System.out.println("*****");
}
- 打印半个金字塔
* //第 1 层 有 1 个*
** //第 2 层 有 2 个*
*** //第 3 层 有 3 个*
**** //第 4 层 有 4 个*
***** //第 5 层 有5个*
public class Switch{
//编写一个main方法
public static void main(String[] args) {
for(int i = 1;i <= 5;i++){//i表示层数
//控制打印每层的*的个数
for(int j = 1;j<=i;j++){
System.out.print("*");
}
//每打印完一层的*后,就换行
System.out.println("");
//println本身会换行,
//或者用System.out.print("n");
}
}
}
-
打印整个金字塔
* //第 1 层 有 1 个* 2 * 1 -1 有 4=(总层数-1)个空格 *** //第 2 层 有 3 个* 2 * 2 -1 有 3=(总层数-2)个空格 ***** //第 3 层 有 5 个* 2 * 3 -1 有 2=(总层数-3)个空格 ******* //第 4 层 有 7 个* 2 * 4 -1 有 1=(总层数-4)个空格 ********* //第 5 层 有 9 个* 2 * 5 -1 有 0=(总层数-5)个空格 public class Switch{ //编写一个main方法 public static void main(String[] args) { for(int i = 1;i <= 5;i++){//i表示层数 //在输出*之前,还要输出 对应空格 = 总层数-当层数 for(int k = 1;k <= 5-i;k++){ System.out.print(" "); } //控制打印每层的*的个数 for(int j = 1;j<=2*i-1;j++){ System.out.print("*"); } //每打印完一层的*后,就换行 System.out.println(""); //println本身会换行, //或者用System.out.print("n"); } } }
-
打印空心的金字塔 [最难的]
* //第 1 层 有 1 个* 当前行的第一个位置是*,最后一个位置也是*
* * 第 2 层 有 2 个* 当前行的第一个位置是*,最后一个位置也是*
* * 第 3 层 有 2 个* 当前行的第一个位置是*,最后一个位置也是*
* * 第 4 层 有 2 个* 当前行的第一个位置是*,最后一个位置也是*
********* //第 5 层 有 9 个* 全部输出*
import java.util.Scanner;
public class Switch{
public static void main(String[] args){
Scanner myScanner = new Scanner(System.in);
System.out.println("输出几行星星:");
int line = myScanner.nextInt();
for(int i=1; i<=line;i++){
for(int k=1;k<=line-i;k++){
System.out.print(" ");//前边的空格数
}
for(int j=1;j<=2*i-1;j++){
if(j==1||j==2*i-1||i==line){ //每行第一个和最后一个和最后一行输出*
System.out.print("*");
}else{
System.out.print(" ");
}
}
System.out.println(" ");//换行
}
}
}
- 自己写的空心菱形
import java.util.Scanner;
public class Switch{
public static void main(String[] args){
Scanner myScanner = new Scanner(System.in);
System.out.println("输出上半部分为几行星星:");
int line = myScanner.nextInt();
//上半部分
for(int i=1; i<=line;i++){
for(int k=1;k<=line-i;k++){
System.out.print(" ");//前边的空格数
}
for(int j=1;j<=2*i-1;j++){
if(j==1||j==2*i-1){ //每行第一个和最后一个和最后一行输出*
System.out.print("*");
}else{
System.out.print(" ");
}
}
System.out.println(" ");//换行
}
//下半部分
for(int a =line-1; a>=1;a--){
for(int c = line-a;c>=1;c--){
System.out.print(" ");
}
for (int b=1;b<=2*a-1;b++){
if(b==1||b==2*a-1){ //每行第一个和最后一个和最后一行输出*
System.out.print("*");
}else{
System.out.print(" ");
}
}
System.out.println(" ");//换行
}
}
}
5.7 跳转控制语句break注意事项
(1)break 语句可以指定退出那层
(2)label1 是标签,名字由程序员指定。
(3)break 后指定到那个label 就退出到哪里。
(4)在实际的开发中,尽量不要使用标签。
(5)如果没有指定 break ,默认退出最近的循环体
-
随机数 random
Math.random() //public static double random() 返回带正号的 double 值,该值大于等于 0.0 且小于 1.0。返回值是一个伪随机选择的数,在该范围内(近似)均匀分布。 //0.4749998761740407 0.41238696627546256 0.08495914852873843 0.034277645140542545 0.3654206938068364 0.45168695756836974 0.6727095226947664 0.4550512902464454 0.810014052676977 0.04461491267967932 0.12219404584351146 (int)(Match.random()*100)+1 //加一是因为,前边乘以100范围是0~99,加1之后范围就到了0~100了。
-
字符串比较 equals
if("丁真".equals(name) && "666".equals(passwd)) { System.out.println("恭喜你,登录成功~"); break; }
判断“丁真”和name这两个字符串是否相等。
5.8 跳转控制语句continue
- continue 语句用于结束本次循环,继续执行下一次循环。
- continue 语句出现在多层嵌套的循环语句体中时,可以通过标签指明要跳过的是哪一层循环 , 这个和前面的标签的 使用的规则一样.
###5.13 跳转控制语句retuen
- return 使用在方法,表示跳出所在的方法,如果 return 写在 main 方法,退出程序。
5.9本章作业
-
求出1-1/2+1/3-1/4…1/100的和
注意1.0/j中的数字1.0不能写成1
//自己写的
public class Switch{
public static void main(String[] args){
double sum=0;
int a=1;
for(int j=1;j<=100;j++){
if(j%2==0){
a=-1;
}else{
a=1;
}
sum=sum+(1.0/j)*a;//这的1.0不能写成1
//写成1的话这个除法1/j得到的就是0了!
}
System.out.println("sum="+sum);
}
}
//老师的
public class Homework08 {
//编写一个main方法
public static void main(String[] args) {
/*
求出1-1/2+1/3-1/4…..1/100的和
思路分析
1. 1-1/2+1/3-1/4…..1/100 = (1/1)-(1/2)+(1/3)-(1/4)...1/100
2. 从上面的分析我们可以看到
(1) 一共有100数 , 分子为1 , 分母从1-100
(2) 还发现 当分母为奇数时,前面是 +, 当分母是偶数时,前面是-
3. 我们可以使用 for + 判断即可完成
4. 把结果存放到 double sum
5. 这里有一个隐藏的陷阱,要把 公式分子 1 写出1.0 才能得到精确的小数
*/
double sum = 0;
for(int i = 1; i <= 100; i++) {
//判断是奇数还是偶数,然后做不同的处理
if( i % 2 != 0) {//分母为奇数
sum += 1.0/i;
} else { //分母我偶数
sum -= 1.0/i;
}
}
System.out.println("sum=" + sum);
}
}
- 求1+(1+2)+(1+2+3)+(1+2+3+4)+…+(1+2+3+…+100)的结果
public class Switch{
public static void main(String[] args){
int sum=0;
for(int i=1;i<=100;i++){
for(int j=1;j<=i;j++){
sum+=j;
}
}
System.out.println("sum="+ sum);
}
}
第 6 章 数组、排序和查找
6.1 冒泡序列
- 这样一层循环只是把最大的一个数排到了最后
public class BubbleSort{
public static void main(String[] args){
int[] arr={24,68,-2,1,6};
int max=0;
for(int i=0;i<arr.length-1;i++){
if(arr[i]>arr[i+1]){
max=arr[i];
arr[i]=arr[i+1];
arr[i+1]=max;
}
System.out.println("第"+(i+1)+"轮");
for(int j=0;j<arr.length;j++){
System.out.print(arr[j]+"t");
}
System.out.println();
}
}
}
-
双重循环最后一下把所有的数从小排到大
public class BubbleSort{ public static void main(String[] args){ int[] arr={24,68,-2,1,6}; int max=0; for(int i=0;i<arr.length-1;i++){ for(int j=0;j<arr.length-i-1;j++) if(arr[j]>arr[j+1]){ max=arr[j]; arr[j]=arr[j+1]; arr[j+1]=max; } System.out.println("第"+(i+1)+"轮"); for(int j=0;j<arr.length;j++){ System.out.print(arr[j]+"t"); } System.out.println(); } } }
6.2 数组的使用
-
使用方式1-动态初始化
数组的定义: 数组类型 数组名[] = new 数据类型[大小]
int a[] = new int[5];
-
使用方式2-动态初始化
数据类型 数组名[]; 也可以 数据类型[] 数组名;
int a[]; 或者 int[] a; //声明数组,这时 a 是 null
数组名 = new 数据类型[大小];
a = new int[10] //分配内存空间,可以存放数据
-
使用方式3-静态初始化
数据类型 数组名[] = {元素值,元素值…}
int a[]={2,5,6,90,65,33}
-
注意:
-
数组创建后,如果没有赋值,有默认值
int 0,short 0, byte 0, long 0, float 0.0,double 0.0,char u0000,boolean false,String null
-
数组属引用类型,数组型数据是对象(object)
-
6.3 数组赋值机制
-
基本数据类型赋值,这个值就是具体的数据,而且相互不影响。
int n1 = 2; int n2 = n1;
int a=10; int b=a; b=80; System.out.println(a);// 10 System.out.println(b);// 80
-
数组在默认情况下是引用传递,赋的值是地址。
public class ArrayDetail{ public static void main(String[] args){ int[] a={1,2,3}; int[] b=a; b[1]=9; for (int i=0;i<a.length;i++){ System.out.print(a[i]+" ");//1 9 3 } System.out.println(); for(int i=0;i<b.length;i++){ System.out.print(b[i]+ " ");//1 9 3 } } }
-
这样数组a和数组b就互不干扰了
重新定义一个数组b
public class ArrayDetail{ public static void main(String[] args){ int[] a={1,2,3}; int[] b=new int[a.length]; for(int i = 0; i < a.length; i++) { b[i] = a[i]; } b[1]=9; for (int i=0;i<a.length;i++){ System.out.print(a[i]+" ");//1 2 3 } System.out.println(); for(int i=0;i<b.length;i++){ System.out.print(b[i]+ " ");//1 9 3 } } }
-
6.4 数组的增加
- 用户可以通过如下方法来决定是否继续添加,添加成功,是否继续?y/n
-
官方答案
import java.util.Scanner; public class ArrayDetail{ public static void main(String[] args){ Scanner myScanner=new Scanner(System.in); int[] arr={1,2,3}; do{ int[] arr2=new int[arr.length +1]; for(int i=0;i<arr.length;i++){ arr2[i]=arr[i]; } System.out.println("请输入你要增加的元素:"); int num=myScanner.nextInt(); arr2[arr2.length - 1]=num; arr=arr2;// 让 arr 指向 arr2; arr = arr2; 那么 原来 arr 数组就被销毁 System.out.println("===arr扩容后元素的情况===="); for(int i=0;i<arr.length;i++){ System.out.print(arr[i]+" "); } //问用户是否继续 System.out.println(); System.out.println("是否继续添加 y/n"); char key = myScanner.next().charAt(0); if(key=='n'){//如果输入n,就结束 break; } }while(true); System.out.println("你退出了增加..."); } }
-
自己写的,在数组int[] arr={1,2,3}的基础上定义增加几个数值,然后录入,输入。(结束后内存里是两个数组,改进是一个)
import java.util.Scanner;
public class ArrayDetail{
public static void main(String[] args){
Scanner myScanner=new Scanner(System.in);
int[] arr={1,2,3};
System.out.println("请输入要加入的个数:");
int n = myScanner.nextInt();
int[] arr2=new int[arr.length+n];
for(int i=0;i<arr.length;i++){
arr2[i]=arr[i];
}
System.out.println("请输入:");
for(int i=0;i<n;i++){
int m=myScanner.nextInt();
arr2[arr.length+i]=m;
}
//1. arr=arr2; 用这个销毁原来的数组arr
for(int i=0;i<arr2.length;i++){ //2. 再把这的arr2换成arr就行了
System.out.print(arr2[i]+" "); // 这种方法比自己的好,能减少一个数组。
}
}
}
6.5 二维数组
-
使用方式 1: 动态初始化
语法: 类型[][] 数组名=new 类型【大小】【大小】
比如: int a[][]=new int[2] [3];
-
使用方式 2: 动态初始化
先声明:类型 数组名[][];
再定义(开辟空间) 数组名 = new 类型[大小] [大小]
赋值(有默认值,比如 int 类型的就是 0)
-
使用方式 3: 动态初始化-列数不确定
int[][] arr = new int[3] [];
-
使用方式 4: 静态初始化
定义 类型 数组名[][] = {{值 1,值 2…},{值 1,值 2…},{值 1,值 2…}}
int[] [] arr = {{1,1,1}, {8,8,9}, {100}};
6.6 杨辉三角形
规律
1.第一行有 1 个元素, 第 n 行有 n 个元素
2. 每一行的第一个元素和最后一个元素都是 1
3. 从第三行开始, 对于非第一个元素和最后一个元素的元素的值. arr[i][j]
arr[i][j] = arr[i-1][j] + arr[i-1][j-1]; //必须找到这个规律
public class ArrayDetail{
public static void main(String[] args){
int[][] yangHui = new int[12][];
for(int i=0;i<yangHui.length;i++){
yangHui[i]=new int[i+1];//给每个一维数组(行)开空间
for(int j= 0;j<yangHui[i].length;j++){
if(j==0 || j==yangHui[i].length-1){
yangHui[i][j]=1;
}else{
yangHui[i][j] = yangHui[i-1][j]+yangHui[i-1][j-1];
}
}
}
//输出杨辉三角形
for(int i=0;i<yangHui.length;i++){
for(int j =0;j<yangHui[i].length;j++){
System.out.print(yangHui[i][j]+"t");
}
System.out.println();
}
}
}
6.7 二维数组使用细节和注意事项
-
一维数组的声明方式有:
int[] x 或者 int x[]
-
二维数组的声明方式有:
int[] [] y 或者 int[] y[] 或者 int y[] []
-
二维数组实际上是由多个一维数组组成的,它的各个一维数组的长度可以相同,也可以不相同。
6.8 本章作业
-
下面数组定义正确的有 B,D
-
String foo = "blue"; boolean[] bar = new booolean[2];//数组bar[]默认的都是false if(bar[0]){ //bar[0]为false,所以不进入 foo="green"; } System.out.println(foo);// 仍然为blue
3.
public class Homework04 {
//编写一个main方法
public static void main(String[] args) {
/*
已知有个升序的数组,要求插入一个元素,该数组顺序依然是升序, 比如:
[10, 12, 45, 90], 添加23 后, 数组为 [10, 12,23, 45, 90]
思路 本质数组扩容 + 定位
1. 我们先确定 添加数应该插入到哪个索引
2. 然后扩容
*/
//先定义原数组
int[] arr = {10, 12, 45, 90};
int insertNum = 111;
int index = -1; //index就是要插入的位置
//遍历 arr数组, 如果发现 insertNum<=arr[i], 说明 i 就是要插入的位置
//使用 index 保留 index = i;
//如果遍历完后,没有发现 insertNum<=arr[i], 说明 index = arr.length
//即:添加到arr的最后
for(int i = 0; i < arr.length; i++) {
if(insertNum <= arr[i]) {
index = i;
break; //找到位置后,就退出
}
}
//判断index 的值
if(index == -1) { //说明没有还没有找到位置
index = arr.length;
}
//扩容
//先创建一个新的数组,大小 arr.length + 1
int[] arrNew = new int[arr.length + 1];
//下面老师准备将arr的元素拷贝到 arrNew ,并且要跳过 index位置
/*
分析:
int[] arr = {10, 12, 45, 90};
arrNew = { }
*/
//i 控制arrNew的下标 , j用来控制arr数组的下标
for(int i = 0, j = 0; i < arrNew.length; i++) {
if( i != index ) { //说明可以把 arr的元素拷贝到 arrNew
arrNew[i] = arr[j];
j++;
} else { //i这个位置就是要插入的数
arrNew[i] = insertNum;
}
}
//让arr 指向 arrNew , 原来的数组,就成为垃圾,被销毁
arr = arrNew;
System.out.println("======插入后,arr数组的元素情况======");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "t");
}
}
}
-
随机生成10个整数(1-100)保存到数组; 在数组中找是否有8
for(int i = 0; i < arr.length; i++) { arr[i] = (int)(Math.random() * 100) + 1; } int findNum = 8; int index = -1; //如果找到,就把下标记录到 index for(int i = 0; i < arr.length; i++) { if(findNum == arr[i]) { System.out.println("找到数" + findNum + " 下标=" + i); index = i; break; } } if(index == -1) { System.out.println("没有找到数" + findNum ); }
第 7 章 面向对象编程(基础部分)
7.1 类与对象
- 类和对象的区别
- 类是抽象的,概念的,代表一类事物,比如人类,猫类…, 即它是数据类型.
- 对象是具体的,实际的,代表一个具体事物, 即 是实例.
- 类是对象的模板,对象是类的一个个体,对应一个实例
7.2对象在内存中存在形式(重要的)必须搞清楚。
7.3 如何创建对象
-
先声明再创建
Cat cat ; //声明对象 cat
cat = new Cat(); //创建
-
直接创建 Cat cat = new Cat();
public class Object{ public static void main(String[] args){ Cat cat1 = new Cat(); cat1.name="小白"; cat1.age=3; cat1.color="白色"; System.out.println("第一只猫的信息"+cat1.name+" "+cat1.age +" "+cat1.color); } } class Cat{ int age; String name; String color; }
7.4 类和对象的内存分配机制
Java 内存的结构分析
- 栈: 一般存放基本数据类型(局部变量)
- 堆: 存放对象(Cat cat , 数组等)
- 方法区:常量池(常量,比如字符串), 类加载信息
Java 创建对象的流程简单分析
- 先加载 Person 类信息(属性和方法信息, 只会加载一次)
- 在堆中分配空间, 进行默认初始化(看规则)
- 把地址赋给 p , p 就指向对象
- 进行指定初始化, 比如 p.name =”jack” p.age = 10
Person a=new Person();
a.age=10;
a.name="小明";
Person b;
b=a;
System.out.println(b.name); //小明
b.age=200;
b=null; //把b的地址null,b现在谁也不指向了
System.out.println(a.age); //200
System.out.println(b.age); //异常
7.5 基本数据类型的传参机制
public class MethodParameter01 {
//编写一个 main 方法
public static void main(String[] args) {
int a = 10;
int b = 20;
//创建 AA 对象 名字 obj
AA obj = new AA();
obj.swap(a, b); //调用 swap
System.out.println("main 方法 a=" + a + " b=" + b);
//a=10 b=20
}
}
class AA {
public void swap(int a,int b){
System.out.println("na 和 b 交换前的值na=" + a + "tb=" + b);//a=10 b=20
//完成了 a 和 b 的交换
int tmp = a;
a = b;
b = tmp;
System.out.println("na 和 b 交换后的值na=" + a + "tb=" + b);//a=20 b=10
}
}
7.6 引用数据类型的传参机制
看一个案例 MethodParameter02.java
B 类中编写一个方法 test100,可以接收一个数组,在方法中修改该数组,看看原来的数组是否变化?会变化
B 类中编写一个方法 test200,可以接收一个 Person(age,sal)对象,在方法中修改该对象属性,看看原来的对象是否变化?会变化.(注意看一个类中怎样调用另一个类。跨类中的方法A类调用B类方法:需要通过对象调用。比如 对象名.方法名(参数) )
public class Object{
public static void main(String[] args){
B b=new B();
int arr[]={1,2,3};
b.test100(arr);
System.out.println("主方法中的");
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+"t");
}
Ren mo = new Ren();
mo.name="jack";
mo.age=20;
b.test200(mo); //注意看这一点
System.out.println(mo.age);
}
}
class Ren{
String name;
int age;
}
class B{
public void test200(Ren mo){ //注意看
mo.age=10000;
}
public void test100(int arr[]){
arr[0]=123;
System.out.println("类中的");
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+"t");
}
}
}
7.7成员方法返回类型是引用类型应用实例
-
编写一个方法 copyPerson,可以复制一个 Person 对象,返回复制的对象。克隆对象, 注意要求得到新对象和原来的 对象是两个独立的对象,只是他们的属性相同。
public class MethodExercise02 { //编写一个main方法 public static void main(String[] args) { Person p = new Person(); p.name = "milan"; p.age = 100; //创建tools MyTools tools = new MyTools(); Person p2 = tools.copyPerson(p); //到此 p 和 p2是Person对象,但是是两个独立的对象,属性相同 System.out.println("p的属性 age=" + p.age + " 名字=" + p.name); System.out.println("p2的属性 age=" + p2.age + " 名字=" + p2.name); //这里老师提示: 可以同 对象比较看看是否为同一个对象 System.out.println(p == p2);//false } } class Person { String name; int age; } class MyTools { //编写一个方法copyPerson,可以复制一个Person对象,返回复制的对象。克隆对象, //注意要求得到新对象和原来的对象是两个独立的对象,只是他们的属性相同 // //编写方法的思路 //1. 方法的返回类型 Person //2. 方法的名字 copyPerson //3. 方法的形参 (Person p) //4. 方法体, 创建一个新对象,并复制属性,返回即可 public Person copyPerson(Person p) { //创建一个新的对象 Person p2 = new Person(); p2.name = p.name; //把原来对象的名字赋给p2.name p2.age = p.age; //把原来对象的年龄赋给p2.age return p2; } }
7.8 递归举例
-
距离问题
-
阶乘问题
public class Recursion01 { //编写一个 main 方法 public static void main(String[] args) { T t1 = new T(); t1.test(4);//输出什么? n=2 n=3 n=4 int res = t1.factorial(5); System.out.println("5 的阶乘 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; } else { return factorial(n - 1) * n; } } }
(老鼠迷宫,汉诺塔,八皇后例子没有写,有空注意一下,很有意思)
7.9 方法重载
- java 中允许同一个类中,多个同名方法的存在,但要求 形参列表不一致!
- 方法名必须相同,形参列表必须相同(形参类型或个数或顺序,至少有一样不同,参数名无要求),返回类型无要求。
7.10 可变参数
-
java 允许将同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法。 就可以通过可变参数实现。
-
基本语法:访问修饰符 返回类型 方法名(数据类型… 形参名) {
}
public int sum(int... nums) {//可以任意多个数相加 int res = 0; for(int i = 0; i < nums.length; i++) { res += nums[i]; } return res; } }
-
可变参数的实参可以为0个活任意多个。
-
可变参数色实参可以为数组。
-
可变参数的本质就是数组
-
可变参数可以和普通类型的参数一起放在有形参列表,但必须保证可变参数在最后
-
一个形参列表中只能出现一个可变参数
-
里边有一个public String showScore(String name ,double… scores)
注意string.
-
public class VarParameterExercise {
//编写一个 main 方法
public static void main(String[] args) {
HspMethod hm = new HspMethod();
System.out.println(hm.showScore("milan" , 90.1, 80.0 ));
System.out.println(hm.showScore("terry" , 90.1, 80.0,10,30.5,70 ));
}
}
class HspMethod {
/*
有三个方法,分别实现返回姓名和两门课成绩(总分),
返回姓名和三门课成绩(总分),返回姓名和五门课成绩(总分)。
封装成一个可变参数的方法
*/
//分析 1. 方法名 showScore 2. 形参(String ,double... ) 3. 返回 String
public String showScore(String name ,double... scores){
double totalScore = 0;
for(int i = 0; i < scores.length; i++) {
totalScore += scores[i];
}
return name + " 有 " +scores.length + "门课的成绩总分为=" + totalScore;
}
}
7.11 作用域
public class VarScopeDetail{
//编写一个 main 方法
public static void main(String[] args) {
Person p1 = new Person();
/*
属性生命周期较长,伴随着对象的创建而创建,伴随着对象的销毁而销毁。
局部变量,生命周期较短,伴随着它的代码块的执行而创建,
伴随着代码块的结束而销毁。即在一次方法调用过程中
*/
//p1.say();//当执行 say 方法时,say 方法的局部变量比如 name,会创建,当 say 执行完毕后
//name 局部变量就销毁,但是属性(全局变量)仍然可以使用
//
T t1 = new T();
t1.test(); //第 1 种跨类访问对象属性的方式
t1.test2(p1);//第 2 种跨类访问对象属性的方式
}
}
class T {
//全局变量/属性:可以被本类使用,或其他类使用(通过对象调用)
public void test() {
Person p1 = new Person();
System.out.println(p1.name);//jack
}
public void test2(Person p) {
System.out.println(p.name);//jack
}
}
class Person {
//细节: 属性可以加修饰符(public protected private..)
// 局部变量不能加修饰符
public int age = 20;
String name = "jack";
public void say() {
//细节 属性和局部变量可以重名,访问时遵循就近原则
String name = "king";
System.out.println("say() name=" + name);
}
public void hi() {
String address = "北京";
//String address = "上海";//错误,重复定义变量
String name = "hsp";//可以
}
}
7.12 构造器
-
基本语法
[修饰符] 方法名(形参列表){
方法体;
}
- 构造器的修饰符可以默认, 也可以是 public protected private
- 构造器没有返回值
- 方法名 和类名字必须一样
- 参数列表 和 成员方法一样的规则
- 构造器的调用, 由系统完成
- 基本介绍
- 构造方法又叫构造器(constructor),是类的一种特殊的方法,它的主要作用是完成对新对象的初始化。它有几个特点:
- 方法名和类名相同
- 没有返回值
- 在创建对象时,系统会自动的调用该类的构造器完成对象的初始化
- 注意事项
7.13 this关键字
- 案例
-
this 的注意事项和使用细节
- this 关键字可以用来访问本类的属性、方法、构造器
- this 用于区分当前类的属性和局部变量
- 访问成员方法的语法:this.方法名(参数列表);
- 访问构造器语法:this(参数列表); 注意只能在构造器中使用(即只能在构造器中访问另外一个构造器, 必须放在第一 条语句)
- this 不能在类定义的外部使用,只能在类定义的方法中使用。
-
this案例
定义 Person 类,里面有 name、age 属性,并提供 compareTo 比较方法,用于判断是否和另一个人相等,提供测试类 TestPerson 用于测试, 名字和年龄完全一样,就返回 true, 否则返回 false-
public class TestPerson { //编写一个 main 方法 public static void main(String[] args) { Person p1 = new Person("mary", 20); Person p2 = new Person("mary", 20); System.out.println("p1 和 p2 比较的结果=" + p1.compareTo(p2)); } } /* 定义 Person 类,里面有 name、age 属性,并提供 compareTo 比较方法, 用于判断是否和另一个人相等,提供测试类 TestPerson 用于测试, 名字和年龄完全一样,就返回 true, 否则返回 false*/ class Person { String name; int age; //构造器 public Person(String name, int age) { this.name = name; this.age = age; } //compareTo 比较方法 public boolean compareTo(Person p) { //名字和年龄完全一样 // if(this.name.equals(p.name) && this.age == p.age) { // return true; // } else { // return false; // } return this.name.equals(p.name) && this.age == p.age; } }
-
7.14 课后作业
-
编程创建一个Cale计算类,在其中定义2个变量表示2个操作数,定义4个方法实现求和、差、乘、商(要求除数为0的话,要提示)并创建2个对象,分别测试。(注意除数中Double的大小写,有点搞不懂)
public class Homework06 { //编写一个main方法 public static void main(String[] args) { Cale cale = new Cale(2, 10); System.out.println("和=" + cale.sum()); System.out.println("差=" + cale.minus()); System.out.println("乘=" + cale.mul()); Double divRes = cale.div(); if(divRes != null) { System.out.println("除=" + divRes); } } } /* 编程创建一个Cale计算类,在其中定义2个变量表示两个操作数, 定义四个方法实现求和、差、乘、商(要求除数为0的话,要提示) 并创建两个对象,分别测试 */ class Cale { double num1; double num2; public Cale(double num1, double num2) { this.num1 = num1; this.num2 = num2; } //和 public double sum() { return num1 + num2; } //差 public double minus() { return num1 - num2; } //乘积 public double mul() { return num1 * num2; } //除法 // public Double div() { //判断 if(num2 == 0) { System.out.println("num2 不能为0"); return null; } else { return num1 / num2; } } }
7.
public class Test { //公有类
int count = 9; //属性
public void count1() { //Test类的成员方法
count=10;//这个count就是属性 改成 10
System.out.println("count1=" + count); //10
}
public void count2() { //Test类的成员方法
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();
Test t1= new Test();
t1.count2();//9
t1.count2();//10
}
}
10.
第8章 面向对象编程(中级部分)
8.1 IDEA 常用快捷键
-
删除当前行, 默认是 ctrl + Y
-
复制当前行,默认是crtl + D
-
补全代码 alt + /
-
添加注释和取消注释 ctrl + / 【第一次是添加注释,第二次是取消注释】
-
导入该行需要的类 先配置 auto import , 然后使用 alt+enter 即可
-
快速格式化代码 ctrl + alt + L
-
快速运行程序 自己定义 alt + R
-
生成构造器等 alt + insert [提高开发效率]
-
查看一个类的层级关系 ctrl + H [学习继承后,非常有用]
-
将光标放在一个方法上,输入 ctrl + B , 可以定位到方法 [学继承后,非常有用]
-
自动的分配变量名 , 通过 在后面假 .var [老师最喜欢的]
8.2 包
8.2.1 包的三大作用
- 区分相同名字的类
- 当类很多时,可以很好的管理类【看Java API文档】
- 控制访问范围
8.2.2 包的基本语法
package.com.student;
- package 关键字,表示打包。
- com.student 表示包名。
8.2.3 包的基本分析
8.2.4 包的命名
-
命名规则:
只能包含数字、字母、下划线、小圆点,但不能用数字开头,不能是关键字或者保留字。
-
命名规范:
一般是小写字母+小圆点
一般是com.公司名.项目名.业务板块名
8.2.5 常用的包
一个包下,包含很多的类,java中常用的包有:
- java.lang.* //lang包是基本包,默认引入,不需要再引入。
- java.util.* //util 包,系统提供的工具包,工具类,使用 Scanner
- java.net.* //网络包,网络开发
- java.awt* //是做java的界面开发,GUI
8.2.6 如何引入包
在java中,为了装载已编译好的包,通常可使用以下三种方法。
-
在要引用的类名前带上包名作为修饰符。
Animals.Cat cat = new Animals Cat();
其中,Animals是包名,Cat是包中的类,cat是类的对象。
-
在文件开头使用 import 引用包中的类。
import Animals.Cat;
class Check{
Cat cat = new Cat( );
}
同样,Animals是包名,Cat是包中的类,cat是创建的Cat类对象。
-
在文件前使用 import 引入整个包。
import Animals. *;
Animals整个包被引入。(在引入包时,可以用点“ . ”表示出包所在的层次结构,如经常使用的:
import java.io.*;
import java.applet.* ;
实际是引入了/java/io/或/java/applet/这样的目录结构下的所有内容。)
8.2.7 注意事项和使用细节
- package 的作用是声明当前类所在的包,需要放在类的最上面,一个类中最多只有一句package。
- import 指令位置放在package的下面,在类定义前面,可以有多句且没有顺序要求。
8.3 访问修饰符
8.3.1基本介绍
java 提供四种访问控制修饰符号,用于控制方法和属性(成员变量)的访问权限(范围):
- 公开级别:用 public 修饰,对外公开
- 受保护级别:用 protected 修饰,对子类和同一个包中的类公开
- 默认级别:没有修饰符号,向同一个包的类公开
- 私有级别:用 private 修饰,只有类本身可以访问,不对外公开
8.3.2 4种访问修饰符的访问范围
8.3.3使用的注意事项
- 修饰符可以用来修饰类中的属性,成员方法以及类
- 只有默认的和public才能修饰类!并且遵循上述访问权限的特点。
- 成员方法的访问规则和属性一样
8.4 面向对象编程三大特征
8.4.1基本介绍
面向对象编程有三大特征:封装、继承和多态。
8.4.2封装介绍
8.4.3封装的理解和好处
8.4.4 封装的实现步骤 (三步)
8.5 面向对象编程-继承
8.5.1 继承基本介绍和示意图
继承可以解决代码复用,让我们的编程更加靠近人类思维.当多个类存在相同的属性(变量)和方法时,可以从这些类中 抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来 声明继承父类即可。画出继承的示意图
8.5.2 继承的基本语法
8.5.3 继承给编程带来的便利
- 代码的复用性提高了
- 代码的扩展性和维护性提高了
8.5.4继承的深入讨论/细节问题
- 子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访 问,要通过父类提供公共的方法去访问
- 子类必须调用父类的构造器, 完成父类的初始化
- 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无 参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过
- 如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)
- super 在使用时,必须放在构造器第一行(super 只能在构造器中使用)
- super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
- java 所有类都是 Object 类的子类, Object 是所有类的基类
- 父类构造器的调用不限于直接父类!将一直往上追溯直到 Object 类(顶级父类)
- 子类最多只能继承一个父类(指直接继承),即 java 中是单继承机制。
- 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关
8.5.5 继承的本质分析(重要)
- 我们看一个案例来分析当子类继承父类,创建子类对象时,内存中到底发生了什么?提示:当子类对象创建好后,建立查找的关系
package com.whwedu.extend_;
/**
* 讲解继承的本质
*/
public class ExtendsTheory {
public static void main(String[] args) {
Son son = new Son();//内存的布局
//?-> 这时请大家注意,要按照查找关系来返回信息
//(1) 首先看子类是否有该属性
//(2) 如果子类有这个属性,并且可以访问,则返回信息
//(3) 如果子类没有这个属性,就看父类有没有这个属性(如果父类有该属性,并且可以访问,就返回信息..)
//(4) 如果父类没有就按照(3)的规则,继续找上级父类,直到 Object...
System.out.println(son.name);//返回就是大头儿子
//System.out.println(son.age);//返回的就是 39
//System.out.println(son.getAge());//返回的就是 39
System.out.println(son.hobby);//返回的就是旅游
}
}
class GrandPa { //爷类
String name = "大头爷爷";
String hobby = "旅游";
}
class Father extends GrandPa {//父类
String name = "大头爸爸";
private int age = 39;
public int getAge() {
return age;
}
}
class Son extends Father { //子类
String name = "大头儿子";
}
- 子类创建的内存布局
8.5.6 案例分析
8.6 super 关键字
8.6.1基本介绍
super 代表父类的引用,用于访问父类的属性、方法、构造器
8.6.2基本语法
8.6.3 super 给编程带来的便利/细节
8.6.4 super 和 this 的比较
8.7 方法重写/覆盖(override)
8.7.1基本介绍
8.7.2 注意事项和使用细节
方法重写也叫方法覆盖,需要满足下面的条件
8.7.3 对方法的重写和重载做一个比较
8.8 面向对象编程-多态
8.8.1 多[多种]态[状态]基本介绍
方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。
8.8.2 多态的具体体
-
方法的多态
重写和重载就体现多态
-
对象的多态 (核心,困难,重点)
多态的前提是:两个对象(类)存在继承关系
8.8.3 多态的向上转型和向下转型
- 向上转型
- 向上转型
package com.whwedu.poly_.detail_;
public class Animal {
String name = "动物";
int age = 10;
public void sleep(){
System.out.println("睡");
}
public void run(){
System.out.println("跑");
}
public void eat(){
System.out.println("吃");
}
public void show(){
System.out.println("hello,你好");
}
}
package com.whwedu.poly_.detail_;
public class Cat extends Animal {
public void eat(){//方法重写
System.out.println("猫吃鱼");
}
public void catchMouse(){//Cat 特有方法
System.out.println("猫抓老鼠");
}
}
package com.whwedu.poly_.detail_;
public class Dog extends Animal {//Dog 是 Animal 的子类
}
package com.whwedu.poly_.detail_;
public class PolyDetail {
public static void main(String[] args) {
//向上转型: 父类的引用指向了子类的对象
//语法:父类类型引用名 = new 子类类型();
Animal animal = new Cat();
Object obj = new Cat();//可以吗? 可以 Object 也是 Cat 的父类
//向上转型调用方法的规则如下:
//(1)可以调用父类中的所有成员(需遵守访问权限)
//(2)但是不能调用子类的特有的成员
//(#)因为在编译阶段,能调用哪些成员,是由编译类型来决定的
//animal.catchMouse();错误
//(4)最终运行效果看子类(运行类型)的具体实现, 即调用方法时,按照从子类(运行类型)开始查找方法
//,然后调用,规则我前面我们讲的方法调用规则一致。
animal.eat();//猫吃鱼.. animal.run();//跑
animal.show();//hello,你好
animal.sleep();//睡
//我希望,可以调用 Cat 的 catchMouse 方法
//多态的向下转型
//(1)语法:子类类型 引用名 =(子类类型)父类引用;
//问一个问题? cat 的编译类型 Cat,运行类型是 Cat
Cat cat = (Cat) animal;
cat.catchMouse();//猫抓老鼠
//(2)要求父类的引用必须指向的是当前目标类型的对象
Dog dog = (Dog) animal; //可以吗? 不可以
System.out.println("ok~~");
}
}
8.8.4 属性没有重写之说!属性的值看编译类型
public class PolyDetail02 {
public static void main(String[] args) {
//属性没有重写之说!属性的值看编译类型
Base base = new Sub();//向上转型
System.out.println(base.count);// ? 看编译类型 10
Sub sub = new Sub();
System.out.println(sub.count);//? 20
}
}
class Base { //父类
int count = 10;//属性
}
class Sub extends Base {//子类
int count = 20;//属性
}
8.8.5 instanceOf 比较操作符
instanceOf 比较操作符,用于判断对象的运行类型是否为 XX 类型或 XX 类型的子类型。
public class PolyDetail03 {
public static void main(String[] args) {
BB bb = new BB();
System.out.println(bb instanceof BB);// true
System.out.println(bb instanceof AA);// true
//aa 编译类型 AA, 运行类型是 BB
//BB 是 AA 子类
AA aa = new BB();
System.out.println(aa instanceof AA);// true
System.out.println(aa instanceof BB);// true
Object obj = new Object();
System.out.println(obj instanceof AA);//false
String str = "hello";
//System.out.println(str instanceof AA);//直接报错,字符串和AA没有任何关系
System.out.println(str instanceof Object);//true
}
}
class AA {} //父类
class BB extends AA{} //子类
8.8.6 java 的动态绑定机制(非常非常重要.)
Java 重要特性: 动态绑定机制
再看一种情况:
public class DynamicBinding {
public static void main(String[] args) {
//a 的编译类型 A, 运行类型 B
A a = new B();//向上转型
System.out.println(a.sum());// 30
System.out.println(a.sum1());// 20
}
}
class A {//父类
public int i = 10;
//动态绑定机制:
public int sum() {//父类 sum()
return getI() + 10;//20 +10
}
public int sum1() {//父类 sum1()
return i + 10;//10 + 10
}
public int getI() {//父类 getI
return i;
}
}
class B extends A {//子类
public int i = 20;
public int getI() {//子类 getI()
return i;
}
}
8.8.7 多态的应用
-
多态数组
数组的定义类型为父类类型,里面保存的实际元素类型为子类类型
应用实例:现有一个继承结构如下:要求创建 1 个 Person 对象、2 个 Student 对象和 2 个 Teacher 对象, 统一放在数组 中,并调用每个对象 say 方法.
应用实例升级:如何调用子类特有的方法,比如 Teacher 有一个 teach , Student 有一个 study 怎么调用?
代码:
package com.whwedu.houserent.view;
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String say() {//返回名字和年龄
return name + "t" + age;
}
}
class Student extends Person {
private double score;
public Student(String name, int age, double score) {
super(name, age);
this.score = score;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
//重写父类 say
@Override
public String say() {
return "学生 " + super.say() + " score=" + score;
}
//特有的方法
public void study() {
System.out.println("学生 " + getName() + " 正在学 java...");
}
}
class Teacher extends Person {
private double salary;
public Teacher(String name, int age, double salary) {
super(name, age);
this.salary = salary;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
//写重写父类的 say 方法
@Override
public String say() {
return "老师 " + super.say() + " salary=" + salary;
}
//特有方法
public void teach() {
System.out.println("老师 " + getName() + " 正在讲 java 课程...");
}
}
public class PloyArray {
public static void main(String[] args) {
//应用实例:现有一个继承结构如下:要求创建 1 个 Person 对象、
// 2 个 Student 对象和 2 个 Teacher 对象, 统一放在数组中,并调用每个对象 say 方法
Person[] persons = new Person[5];
persons[0] = new Person("jack", 20);
persons[1] = new Student("mary", 18, 100);
persons[2] = new Student("smith", 19, 30.1);
persons[3] = new Teacher("scott", 30, 20000);
persons[4] = new Teacher("king", 50, 25000);
for (int i = 0; i < persons.length; i++) {
//老师提示: person[i] 编译类型是 Person ,运行类型是是根据实际情况有 JVM 来判断
System.out.println(persons[i].say());//动态绑定机制
//这里大家聪明. 使用 类型判断 + 向下转型.
if (persons[i] instanceof Student) {//判断 person[i] 的运行类型是不是 Student
Student student = (Student) persons[i];//向下转型
student.study();
//小伙伴也可以使用一条语句 ((Student)persons[i]).study();
} else if (persons[i] instanceof Teacher) {
Teacher teacher = (Teacher) persons[i];
teacher.teach();
} else if (persons[i] instanceof Person) {
//System.out.println("你的类型有误, 请自己检查...");
} else {
System.out.println("你的类型有误, 请自己检查...");
}
}
}
}
-
多态参数
方法定义的形参类型为父类类型,实参类型允许为子类类型
package com.whwedu.houserent.view;
public class Employee {
private String name;
private double salary;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
//得到年工资的方法
public double getAnnual() {
return 12 * salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
package com.whwedu.houserent.view;
public class Manager extends Employee {
private double bonus;
public Manager(String name, double salary, double bonus) {
super(name, salary);
this.bonus = bonus;
}
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
public void manage() {
System.out.println("经理 " + getName() + " is managing");
}
//重写获取年薪方法
@Override
public double getAnnual() {
return super.getAnnual() + bonus;
}
}
package com.whwedu.houserent.view;
public class Worker extends Employee {
public Worker(String name, double salary) {
super(name, salary);
}
public void work() {
System.out.println("普通员工 " + getName() + " is working");
}
@Override
public double getAnnual() { //因为普通员工没有其它收入,则直接调用父类方法
return super.getAnnual();
}
}
package com.whwedu.houserent.view;
public class PloyParameter {
public static void main(String[] args) {
Worker tom = new Worker("tom", 2500);
Manager milan = new Manager("milan", 5000, 200000);
PloyParameter ployParameter = new PloyParameter();
ployParameter.showEmpAnnual(tom);
ployParameter.showEmpAnnual(milan);
ployParameter.testWork(tom);
ployParameter.testWork(milan);
}
//showEmpAnnual(Employee e)
//实现获取任何员工对象的年工资,并在 main 方法中调用该方法 [e.getAnnual()]
public void showEmpAnnual(Employee e) {
System.out.println(e.getAnnual());//动态绑定机制.
}
//添加一个方法,testWork,如果是普通员工,则调用 work 方法,如果是经理,则调用 manage 方法
public void testWork (Employee e){
if (e instanceof Worker) {
((Worker) e).work();//有向下转型操作
} else if (e instanceof Manager) {
((Manager) e).manage();//有向下转型操作
} else {
System.out.println("不做处理...");
}
}
}
8.9 Object 类详解
8.9.1 equals方法
==和 equals 的对比 [面试题]
== 是一个比较运算符
- == :既可以判断基本类型,又可以判断引用类型
- == :如果判断基本类型,判断的是值是否相等。实例: int i = 10; doublt d = 10.0;
- == :如果判断引用类型,判断的是地址是否相等,即判定是不是同一对象。
- equals :是Object类中的方法,只能判断引用类型。(可以查看Jdk源码)
- 默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等。比如:Integer,String【看看String 和 Integer的 equals 源代码】
8.9.2 hashCode 方法
几个小结:
- 提高具有哈希结构的容器的效率!
- 两个引用,如果指向的是同一个对象,则哈希值肯定是一样的!
- 两个引用,如果指向的是不同对象,则哈希值是不一样的
- 哈希值主要根据地址号来的!, 不能完全将哈希值等价于地址
8.9.3 toString 方法
-
基本介绍
默认返回:全类名+@+哈希值的十六进制,【查看 Object 的 toString 方法】
子类往往重写 toString 方法,用于返回对象的属性信息
-
重写 toString 方法,打印对象或拼接对象时,都会自动调用该对象的 toString 形式
-
当直接输出一个对象时,toString 方法会被默认的调用, 比如 System.out.println(monster); 就会默认调用 monster.toString()
8.9.4 finalize 方法
- 当对象被回收时,系统自动调用该对象的 finalize 方法。子类可以重写该方法,做一些释放资源的操作
- 什么时候被回收:当某个对象没有任何引用时,则 jvm 就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来 销毁该对象,在销毁该对象前,会先调用 finalize方法
- 垃圾回收机制的调用,是由系统来决定(即有自己的 GC 算法), 也可以通过 System.gc() 主动触发垃圾回收机制
8.10 断点调试(debug)
8.10.1 一个实际需求
8.10.2 断点调试介绍
8.10.3 断点调试的快捷键
F7(跳入) F8(跳过) shift+F8(跳出) F9(resume,执行到下一个断点)
最后
以上就是清爽饼干为你收集整理的Java初学者零基础分章学习后续第5章 程序控制结构第 6 章 数组、排序和查找第 7 章 面向对象编程(基础部分)第8章 面向对象编程(中级部分)的全部内容,希望文章能够帮你解决Java初学者零基础分章学习后续第5章 程序控制结构第 6 章 数组、排序和查找第 7 章 面向对象编程(基础部分)第8章 面向对象编程(中级部分)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复