当前位置: 首页 > news >正文

Java面向对象基础学习笔记

面向对象基础

-类解决的问题

已学技术:

  1. 单独地定义变量
  2. 使用数组

使用已学技术的问题

  1. 不利于数据管理
  2. 效率低

类解决的问题的方法

  1. 用成员变量名直观展现变量含义
  2. 可批量操作对象,效率高

-类与对象

  • 类与对象的关系

    • 类是把对象的所有属性和行为提取出来后的一种自定义数据类型
    • 对象是类的一个具体的实例
    • java最大的特点就是面向对象
  • 类与对象的区别与联系

    1. 类是抽象的,概念的,代表一类事物,比如人类,猫类。。。即它是数据类型
    2. 对象是具体的,实际的,代表一个具体事物,即,是实例
    3. 类是对象的模板,对象是类的一个个体,对应一个实例
  • 对象在内存中的存在形式

    对象变量存储在栈中,对象指向的数据存储在堆中,对象中的引用类型数据存储在方法区中

  • 属性/成员变量

    • 基本介绍
      1. 从概念或叫法上看: 成员变量 =属性 = field(即 成员变量是用来表示属性的,授课中,统一叫属性)。
      2. 属性是类的一个组成部分,一般是基本数据类型,也可是引用类型(对象,数组)。比如我们前面定义猫类 的 int age 就是属性。
    • 注意事项和细节说明
      1. 属性的定义语法同变量,示例:访问修饰符(public protected 默认 private) 属性类型 属性名。
      2. 属性的定义类型可以为任意类型,包含基本类型或引用类型。
      3. 属性如果不赋值,有默认值,规则和数组一致。
  • 创建对象的两种形式

    1. 先声明再创建

      Cat cat ;
      cat = new Cat();
      
    2. 直接创建

      Cat cat = new Cat();
      
  • 如何访问属性

    基本语法:对象名.属性名

    cat.name;
    cat.age
    cat.color;
    
  • 类和对象的内存分配机制

    Java内存的结构分析

    1. 栈: 一般存放基本数据类型(局部变量)
    2. 堆:存放对象(Cat cat,数组等)
    3. 方法区:常量池(常量,比如字符串),类加载信息
Person p1=new Person();//在方法区加载Person类的属性信息和方法信息;在堆中为新的对象开辟空间并初始化属性值;在栈中创建一个Person类的p1变量;使p1指向堆中新开辟的空间
p1.age=10;//使栈中p1变量指向的堆中的对象空间的age都值变为10
p1.name="小明”;//在方法区中新建常量‘小明’;使p1指向堆中对象区域的name指向方法区中新建的常量
Person p2=p1;//把p1 赋给了 p2, 让p2指向p1
System.out.println(p2.age);//此时p2与p1指向堆中同一个对象的内存区域

-成员方法

  • 基本介绍
    在某些情况下,我们要需要定义成员方法(简称方法)。比如人类:除了有一些属性外( 年龄姓名…),我们人类还有一些行为比如:可以说话、跑步…,通过学习,还可以做算术题。这时就要用成员方法才能完成。现在要求对Person类完善。

  • 成员方法快速入门

    1. 添加speak 成员方法,输出 我是一只好人

    2. 添加cal01 成员方法,可以计算从 1+…+1000的结果

    3. 添加cal02 成员方法,该方法可以接收一个数n,计算从 1+…+n 的结果

    4. 添加getsum成员方法,可以计算两个数的和

      /***	 1. 添加speak 成员方法,输出 我是一只好人* 2. 添加cal01 成员方法,可以计算从 1+..+1000的结果* 3. 添加cal02 成员方法,该方法可以接收一个数n,计算从 1+..+n 的结果* 4. 添加getsum成员方法,可以计算两个数的和*/
      public class Method01{public static void main(String[] args){People p1=new People();p1.age=20;p1.name="小明";People p2=p1;System.out.println(p2.age);System.out.println(p2.name);p2.speak();p2.call01();p2.call02(100);p2.getSum(11,22);}
      }class People{public int age;public String name;public void speak(){System.out.println("我是一只好人");}public void call01(){int sum=0;for(int i=1;i<=1000;i++){sum+=i;}System.out.println(" 1+2+3+..+1000="+sum);}public void call02(int n){int sum=0;for(int i=1;i<=n;i++){sum+=i;}System.out.println(" 1+2+3+..+n="+sum);}public void getSum(int a, int b){System.out.println(a+" + "+b+" = "+(a+b));}
      }
      
  • 方法调用的机制原理

  1. 当程序执行到方法时,就会开辟一个独立的空间(栈空间)
  2. 当方法执行完毕,或者执行到return语句时,就会返回.
  3. 返回到调用方法的地方
  4. 返回后,继续执行方法后面的代码
  5. 当main方法(栈)执行完毕,整个程序退出
  • 成员方法的好处

    1. 提高代码复用性
    2. 可以将实现细节封装起来,供其他用户调用
  • 成员方法的定义

    public 返回数据类型 方法名 (形参列表...){语句;...;return 返回值;
    }
    
    1. 形参列表:表示成员方法输入 。
    2. 数据类型(返回类型):表示成员方法输出,void 表示没有返回值。
    3. 方法主体:表示为了实现某一功能代码块。
    4. return 语句不是必须的。
  • 注意事项和使用细节

    • 修饰符(作用是控制方法使用的范围)

      可选,有public、默认、protected、private四种

    • 返回类型

      1. 一个方法最多一个返回值
      2. 返回类型可以为任意类型,包含基本类型或引用类型
      3. 如果方法要求有返回数据类型,则方法体中最后执行语句必须为return值;而且要求返回值类型必须和return的值类型一致或兼容
      4. 如果方法是void,则方法体中可以没有return语句,或者只写return;
    • 方法名

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

    • 参数列表

      1. 一个方法可以有0个参数,也可以有多个参数,中间用逗号隔开
      2. 参数类型可以为任意类型,包含基本类型或引用类型
      3. 调用带参数的方法时,一定对应着参数列表传入相同类型或兼容类型的参数
      4. 方法定义时的参数称为形式参数,简称形参;方法调用时的参数称为实际参数,简称实参,实参和形参的类型要一致或兼容、个数、顺序必须一致!
    • 方法体

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

    • 方法细节调用说明

      1. 同一个类中的方法调用:直接调用即可。比如 print(参数);案例演示:A类 sayOk 调用 print()
      2. 跨类中的方法A类调用B类方法:需要通过对象名调用。比如对象名.方法名(参数);案例演示:B类 sayHello 调用 print()
      3. 特别说明一下:跨类的方法调用和方法的访问修饰符相关,先暂时这么提一下后面我们讲到访问修饰符时,还要再细说。
  • 成员方法练习

/*** 定义一个类AA,包含两个方法* 第一个方法判断传入的整数是否是奇数* 第二个方法输出一个n行m列的*阵列*/
public class MethodExercise01{public static void main(String[] args){AA aa=new AA();int num=101;if(aa.isOdd(num)){System.out.println(num+"是奇数");}else{System.out.println(num+"是偶数");}aa.printStarGrid(5,7);}	
}class AA{//第一个方法判断传入的整数是否是奇数public boolean isOdd(int n){return n%2==1?true:false;}//第二个方法输出一个n行m列的*阵列public void printStarGrid(int n,int m){for(int i=0;i<n;i++){for(int j=0;j<m;j++){System.out.print("*\t");}System.out.println("");}}
}
  • 成员方法传参机制

    • 基本数据类型传参

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

    • 引用数据类型的传参

      数组和对象都属于引用类型,引用类型传递的是地址(传递也是值,但是值是地址),可以通过形参影响实参!

  • 成员方法传参练习

    编写类MyTools类,包含两个方法

    第一个方法可以打印二维数组的数据。
    第二个方法copyPerson,可以复制一个Person对象,返回复制的对象。克隆对象,注意要求得到新对象和原来的对象是两个独立的对象,只是他们的属性相同、

    /*** 编写类MyTools类,包含两个方法* 第一个方法可以打印二维数组的数据* 第二个方法copyPerson,可以复制一个Person对象,返回复制的对象。克隆对象,注意要求得到新对象和原来的对象是两个独立的对象,只是他们的属性相同*/
    public class MethodExercise02{public static void main(String[] args){MyTool myTool=new MyTool();//打印二维数组演示int[][] metrix={{1,2,3},{4,5,6},{7,8,9,10,11}};//对象复制演示Person p1,p2;p1=new Person();p1.name="Xiao Wang";p1.age=20;p2=null;p1.printInfo();System.out.println(p2);p2=myTool.copyPerson(p1);p1.printInfo();p2.printInfo();}	
    }class MyTool{//第一个方法可以打印二维数组的数据public void print2DArray(int[][] metrix){int rowSize=metrix.length;for(int i=0;i<rowSize;i++){for(int j=0;j<metrix[i].length;j++){System.out.print(metrix[i][j]);}System.out.println();}}//复制Person对象,返回一个Personpublic Person copyPerson(Person p1){Person p=new Person();p.age=p1.age;p.name=p1.name;return p;}
    }class Person{int age;String name;public void printInfo(){System.out.println("名字:"+this.name+"\n年龄:"+this.age);}
    }
    

-方法递归调用

  • 基本介绍

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

  • 递归能解决什么问题?

    1. 各种数学问题如: 8皇后问题,汉诺塔,阶乘问题,迷宫问题,球和篮子的问题(google编程大赛)[简单演示]
    2. 各种算法中也会使用到递归,比如快排,归并排序,二分查找,分治算法等
    3. 将用栈解决的问题–>递归代码比较简洁
  • 递归重要规则

    1. 执行一个方法时,就创建一个新的受保护的独立空间(栈空间)
    2. 方法的局部变量是独立的,不会相互影响,比如n变量
    3. 如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据
    4. 递归必须向退出递归的条件逼近,否则就是无限递归,出现StackOverflowError,死龟了:)
    5. 当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当方法执行完毕或者返回时,该方法也就执行完毕。
  • 递归练习

    1. 请使用递归的方式求出斐波那契数1,1,2,3,5,8,13…给你一个整数n,求出它的值是多少

    2. 猴子吃桃子问题:有一堆桃子,猴子第一天吃了其中的一半并再多吃了一个!以后,每天猴子都吃其中的一半,然后再多吃一个。当到第10天时,想再吃时(即还没吃),发现只有1个桃子了。问题:最初共多少个桃子?

      /*** 1. 请使用递归的方式求出斐波那契数1,1,2,3,5,8,13...给你一个整数n,求出它的值是多少* 2. 猴子吃桃子问题:有一堆桃子,猴子第一天吃了其中的一半并再多吃了一个!以后,每天猴子都吃其中的一半,然后再多吃一个。当到第10天时,想再吃时(即还没吃),发现只有1个桃子了。问题:最初共多少个桃子?*/
      public class RecursionExercise01{public static void main(String[] args){T t=new T();int n=7;System.out.println(t.fibonacci(n));System.out.println(t.peachNum(1));}
      }class T{public int fibonacci(int n){if(n<3){return 1;}else{return fibonacci(n-1)+fibonacci(n-2);}}public int peachNum(int day){if(day==10)return 1;return 2*(peachNum(day+1)+1);}
      }
      
    3. 迷宫问题,从地图的左上角走到地图的右下角

      /*** 走迷宫问题,起点在(1,1),终点在(rows-2,columns-2)*/
      public class RecursionExercise02{public static void main(String[] args){//初始化工具类T t=new T();//定义迷宫的行数和列数int rows=8;int columns=9;//定义初始迷宫地图,1表示墙,0表示空地,2表示通路,3表示死路int[][] map=new int[rows][columns];//刷墙for(int i=0;i<rows;i++){map[i][0]=1;map[i][columns-1]=1;}for(int i=0;i<columns;i++){map[0][i]=1;map[rows-1][i]=1;}//设置额外的墙map[1][4]=1;map[2][3]=1;map[2][4]=1;//输出初始地图t.printMap(map,rows,columns);//找路t.findWay(map,rows,columns,1,1);//输出路线地图t.printMap(map,rows,columns);}
      }class T{//输出地图public void printMap(int[][] map,int rows, int columns){System.out.println("----------------------------");for(int i=0;i<rows;i++){for(int j=0;j<columns;j++){System.out.print(map[i][j]+"\t");}System.out.println("");}System.out.println("----------------------------");}//递归找路public boolean findWay(int[][] map,int rows, int columns,int n,int m){//如果到终点,则走完了,否则继续走if(n==rows-2&&m==columns-2){map[n][m]=2;return true;}else{//如果此地是空地,则继续找路,否则返回falseif(map[n][m]==0){//假设可以走这步map[n][m]=2;//找路策略,上-右-下-左,若可以走,则标记2,若是死路则标记3if(findWay(map,rows,columns,n-1,m)){return true;}else if(findWay(map,rows,columns,n,m+1)){return true;}else if(findWay(map,rows,columns,n+1,m)){return true;}else if(findWay(map,rows,columns,n,m-1)){return true;}else{map[n][m]=3;return false;}}else{return false;}}}
      }
      
    4. 汉诺塔

    //实现汉诺塔
    public class HanoiTower{public static void main(String[] args){//初始化塔工具类TowerTools towerTools=new TowerTools();//汉诺依塔高度int height=5;//初始塔int[][] hanoiTower=new int[height][3];towerTools.initTower(hanoiTower,height);//输出初始塔towerTools.printTower(hanoiTower,height);//移动塔towerTools.moveTower(hanoiTower,height,height,0,1,2);}
    }class TowerTools{//初始化塔方法public void initTower(int[][] tower,int height){//第一列从上往下初始化为1~heightfor(int i=0;i<height;i++){tower[i][0]=i+1;}//第二第三列初始化为0for(int i=0;i<height;i++){tower[i][1]=0;tower[i][2]=0;}}//输出塔方法public void printTower(int[][] tower,int height){//输出一行分隔符System.out.println("-----------------------");//输出全部for(int i=0;i<height;i++){for(int j=0;j<3;j++){System.out.print(tower[i][j]+"\t");}System.out.println("");}//输出一行分隔符System.out.println("-----------------------");}//策略方法,把n数量的盘子从a号杆移动到c号杆,借助b号杆public void moveTower(int[][] tower,int height,int n,int a,int b,int c){//如果n是1,则直接移动,否则先移动上面的盘子再移动底部的盘子if(n==1){//直接移动moveDisk(tower,height,a,c);}else{//先移动上面的盘子,借助目标杆到辅助杆moveTower(tower,height,n-1,a,c,b);//移动底部盘子到目标杆moveDisk(tower,height,a,c);//把上面的盘子借助初始杆移动到目标杆moveTower(tower,height,n-1,b,a,c);}}//负责移动盘子的方法,从a号柱移动到b号柱,移动后自动输出public boolean moveDisk(int[][] tower,int height,int a,int b){//a柱和b柱顶端盘子序号int aTop=0;int bTop=0;//找到a号柱顶端序号while(aTop<height&&tower[aTop][a]==0){aTop++;}//找到b号柱顶端序号while(bTop<height&&tower[bTop][b]==0){bTop++;}//若aTop超限或bTop超限或bTop是顶端盘子或在bTop盘子存在的情况下aTop盘子大于等于bTop盘子则返回falseif(aTop>height-1||bTop>height||bTop==0||tower[bTop-1][b]!=0&&tower[aTop][a]>=tower[bTop-1][b]){return false;}//把盘子从a号柱移动到b号柱tower[bTop-1][b]=tower[aTop][a];tower[aTop][a]=0;//输出System.out.println((a+1)+" -> "+(b+1));this.printTower(tower,height);return true;}
    }
    
    1. 八皇后问题
    /*
    八皇后问题,把八个皇后放在棋盘上,使它们任意两个都不在同一行同一列或同一斜线上,输出所有解
    */
    public class EightQueen{public static void main(String[] args){//初始化工具类Tools tools=new Tools();//用一维数组表示皇后的位置,皇后可以在0-7的位置上int[] queenPos=new int[8];//初始化tools.initQueenPos(queenPos);//打印初始棋盘tools.printBoard(queenPos);//寻找解tools.findAnswer(queenPos,0);}
    }//工具类
    class Tools{//初始化,-1表示皇后未分配位置public void initQueenPos(int[] queenPos){for(int i=0;i<8;i++){queenPos[i]=-1;}}//打印棋盘,0表示空位,1表示皇后public void printBoard(int[] queenPos){System.out.println("------------------------");for(int i=0;i<8;i++){for(int j=0;j<8;j++){//如果j是皇后的位置就输出1,否则输出0System.out.print((j==queenPos[i]?1:0)+"\t");}System.out.println("");}System.out.println("------------------------");}//寻找解的递归方法,检查第n行的8个位置是否可以放皇后public void findAnswer(int[] queenPos,int n){//n等于8,代表8个皇后都已就位,输出结果;否则继续检查此行是否有位置可以放皇后。if(n==8){printBoard(queenPos);}else{//遍历第n行的所有位置,检查是否可以放皇后for(int i=0;i<8;i++){//假设n行i列可以放皇后queenPos[n]=i;//检查是否正确,若正确则继续递归,否则继续检查if(ifNQueenFit(queenPos,n)){findAnswer(queenPos,n+1);	}}//第n行遍历结束,回溯queenPos[n]=-1;}}//检查第n行的皇后位置是否合适public boolean ifNQueenFit(int[] queenPos,int n){//如果n是0(第一行)则直接返回合适,否则继续检查if(n==0){return true;}else{for(int i=0;i<n;i++){//(i,queenPos[i]) (n,queenPos[n]),若在在同一列或斜线上就不行 if(queenPos[i]==queenPos[n]||i-n==queenPos[i]-queenPos[n]||n-i==queenPos[i]-queenPos[n]){return false;}}//检查完毕,此位置可放return true;}}
    }
    

-方法重载

  • 基本介绍

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

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

  • 重载的好处

    1. 减轻了起名的麻烦
    2. 减轻了记名的麻烦
  • 注意事项和使用细节

    1. 方法名 :必须相同
    2. 形参列表:必须不同(参数类型或个数或顺序,至少有一样不同,参数名无要求)
    3. 返回类型:无要求

-可变参数

  • 基本概念
    java允许将同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法,就可以通过可变参数实现

  • 基本语法

    访问修饰符 返回类型 方法名(数据类型... 形参名){.........
    }
    
  • 注意事项和使用细节

    1. 可变参数的实参可以为0个或任意多个。
    2. 可变参数的实参可以为数组。
    3. 可变参数的本质就是数组.
    4. 可变参数可以和普通类型的参数一起放在形参列表,但必须保证可变参数在最后
    5. 一个形参列表中只能出现一个可变参数
  • 练习

    有三个方法,分别实现返回姓名和两门课成绩(总分),返回姓名和三门课成绩(总分),返回姓名和五门课成绩(总分)。封装成一个可变参数的方法

    类名 HspMethod 方法名 showscore

    /*
    有三个方法,分别实现返回姓名和两门课成绩(总分),返回姓名和三门课成绩(总分),返回姓名和五门课成绩(总分)。封装成一个可变参数的方法      
    类名 HspMethod 方法名 showscore     
    */
    public class VarArgExercise{public static void main(String[] args){System.out.println(HspMethod.showscore("小明",85,70.5,97,79,85));}
    }class HspMethod{public static String showscore(String name, double... scores){int len=scores.length;double sum=0;for(int i=0;i<len;i++){sum+=scores[i];}return name+"同学你好,你考了"+len+"门科目,总分是"+sum;}
    }
    

-作用域

  • 基本使用

    面向对象中,变量作用域是非常重要知识点

    1. 在java编程中,主要的变量就是属性(成员变量)和局部变量。
    2. 我们说的局部变量一般是指在成员方法中定义的变量。
    3. java中作用域的分类
      1. 全局变量:也就是属性,作用域为整个类体
      2. 局部变量:也就是除了属性之外的其他变量,作用域为定义它的代码块中!
    4. 全局变量可以不赋值,直接使用,因为有默认值,局部变量必须赋值后,才能使用,因为没有默认值。
  • 注意事项和细节使用

    1. 属性和局部变量可以重名,访问时遵循就近原则。

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

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

    4. 作用域不同。

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

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

    5. 修饰符不同。

      全局变量/属性可以加修饰符

      局部变量不可以加修饰符

-构造方法/构造器

  • 看一个需求
    我们来看一个需求:前面我们在创建人类的对象时,是先把一个对象创建好后,再给他的年龄和姓名属性赋值,如果现在我要求,在创建人类的对象时,就直接指定这个对象的年龄和姓名,该怎么做?这时就可以使用构造器。

  • 基本语法

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

    ​ 方法体;

    }

  • 基本介绍
    构造方法又叫构造器(constructor),是类的一种特殊的方法,它的主要作用是完成对新对象的初始化。它有几个特点:

    1. 方法名和类名相同
    2. 没有返回值
    3. 在创建对象时,系统会自动的调用该类的构造器完成对对象的初始化,
  • 注意事项和使用细节

    1. 一个类可以定义多个不同的构造器,即构造器重载

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

    2. 构造器名和类名要相同

    3. 构造器没有返回值

    4. 构造器是完成对象的初始化,并不是创建对象

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

    6. 如果程序员没有定义构造方法,系统会自动给类生成一个默认无参构造方法(也叫默认构造方法),比如 Person (){}, 使用javap指令 反编译看看

    7. 一旦定义了自己的构造器,默认的构造器就覆盖了就不能再使用默认的无参构造器,除非显式的定义一下,即:Person(){}

-构造器练习

​ 在前面定义的Person类中添加两个构造器:

​ 第一个无参构造器:利用构造器设置所有人的age属性初始值都为18。
​ 第二个带pName和pAge两个参数的构造器:使得每次创建Person对象的同时初始化对象的age属性值和name属性值。分别使用不同的构造器,创建对象。

public class ConstructorExercise{public static void main(String[] args){Person p1=new Person();Person p2=new Person(20,"Kate");System.out.println(p1.age+p1.name);System.out.println(p2.age+p2.name);}
}class Person{int age;String name;Person(){this.age=18;}Person(int pAge,String pName){this.age=pAge;this.name=pName;}
}

-对象创建的流程

  1. 若方法区中没有该类,则加载该类的信息
  2. 在堆中为对象分配空间和地址
  3. 完成对象初始化(默认初始化、显式初始化、构造器初始化)
  4. 将堆中对象的地址返回给栈中对象变量

-this关键字

  • 需求

    将构造器的形参命名为和类属性一样。

  • 什么是this
    java虚拟机会给每个对象分配 this,代表当前对象。

  • this的本质

​ 在对象所分配的堆内存中,指向调用this关键字的对象本身;哪个对象调用,this就指向哪个对象。

  • this的注意事项和使用细节

    1. this关键字可以用来访问本类的属性、方法、构造器
    2. this用于区分当前类的属性和局部变量
    3. 访问成员方法的语法:this.方法名(参数列表);
    4. 访问构造器语法:this(参数列表);注意只能在构造器中使用,即只能在构造器中访问另一个构造器,必须放在第一条语句
    5. this不能在类定义的外部使用,只能在类定义的方法中使用。
  • 练习

    定义Person类,里面有name、age属性,并提供compareTo比较方法,用于判断是否和另一个人相等,提供测试类TestPerson用于测试,名字和年龄完全一样,就返回true,否则返回false

/*
定义Person类,里面有name、age属性,并提供compareTo比较方法,用于判断是否和另一个人相等,提供测试类TestPerson用于测试,名字和年龄完全一样,就返回true,否则返回false
*/public class TestPerson{public static void main(String[] args){Person p1=new Person(19,"Xiaoming");Person p2=new Person(19,"Xiaoming");Person p3=new Person(18,"Xiaoming");Person p4=new Person(19,"lala");Person p5=null;System.out.println(p1.compareTo(p2));System.out.println(p1.compareTo(p3));System.out.println(p1.compareTo(p4));System.out.println(p1.compareTo(p5));}
}class Person{int age;String name;Person(int age,String name){this.age=age;this.name=name;}public boolean compareTo(Person p){//如果p是空,或者name或age不相等,两个对象不同if(p==null||this.name!=p.name||this.age!=p.age){return false;}else{return true;}}
}

相关文章:

  • 字体样式集合
  • AI:人形机器人一定是人的形状吗?
  • 题单:汉诺塔问题
  • 深入了解 VPC 端点类型 – 网关与接口
  • Java的线程通信机制是怎样的呢?
  • Java、ssm(AI) 2025/5/17
  • MySQL 中 JOIN 和子查询的区别与使用场景
  • 《棒球万事通》球类运动有哪些项目·棒球1号位
  • 5.2.1_2二叉树的性质
  • Autosar Nvm下电存储实现方式-基于ETAS工具
  • Codeforces Round 1024 (Div.2)
  • Mysql数据库之集群进阶
  • 日志系统**
  • 在WSL中的Ubuntu发行版上安装Anaconda、CUDA、CUDNN和TensorRT
  • 深度学习(第3章——亚像素卷积和可形变卷积)
  • 从零开发 1688 数据接口:商品详情页实时采集 API 接入详解
  • VC++6.0分步执行常见问题及解决方案
  • Redis——三大策略
  • TTS:F5-TTS 带有 ConvNeXt V2 的扩散变换器
  • TXT记录解析技术深度解析与应用实践
  • 常州新型碳材料集群产值近二千亿,请看《浪尖周报》第24期
  • 种植耐旱作物、启动备用水源,甘肃各地多举措应对旱情
  • 第十一届世界雷达展开幕,尖端装备、“大国重器”集中亮相
  • 上海交大曾小勤:科技传播不应停留于知识搬运,要做科学思维的播种机
  • 九江宜春领导干部任前公示,3人拟提名为县(市、区)长候选人
  • 体坛联播|巴萨提前2轮西甲夺冠,郑钦文不敌高芙止步4强