2.1 Java特点
2.2 Java运行机制及运行过程
JDK基本介绍
1.JDK全称(Java Development Kit Java开发工具包)
JDK=JRE+java的开发工具【java、javac、javadoc、javap等】
2.JDK是提供给java开发人员使用的,其中包含了java的开发工具,也包括了JRE。所以安装了JDK,就不用再单独安装JRE了
JRE基本介绍
1.JRE(java Runtime Environment java运行环境)
JRE=JVM+Java的核心类库【类】
2.包括java虚拟机(JVM java Virtual Machine)和java程序所需的核心类库等,如果想要运行一个开发好的java程序,计算机中只需要安装JRE即可
JDK、JRE和JVM的包含关系
1.JDK=JRE+开发工具集(例如javac、java编译工具等)
2.JRE=JVM+java SE标准类库
3.如果只想运行开发好的.class文件,只需要JRE
2.3 Java开发注意事项和细节说明
2.4 Java转义字符
2.5 Java易犯错误
2.6 注释
PS:选中要注释的部分,按 ctrl+shift+/ 进行注释,或者输入完 /** +tab 自动补全
2.7 Java代码规范
2.8 DOS常用指令(了解)
2.8.1 DOS基本原理
2.8.2 相对路径和绝对路径
2.8.3 常用DOS指令
3.1 程序中+号的使用
3.2 数据类型
3.3 整数类型
3.3.1 整型的类型
3.3.2 整型的使用细节
3.4.2 浮点型使用细节
PS:浮点数不一定是一个确定的数,所以当我们对运算结果是小数的进行相等判断时,要小心精度的比较。应该是以两个数的差值的绝对值,在某个精度范围内判断来判断这两个浮点数相等
3.5 Java API文档
PS(修改快捷键):首选项---->按键绑定(默认)—>ctrl+F进行查找,复制原话—>按键绑定(用户),进行粘贴和修改,并且保存!
3.6.2 字符类型使用细节
PS:字符类型的本质是整数
3.7 常用编码
3.7.1 ASCII编码
3.7.2 Unicode编码
3.7.3 UTF-8编码
3.8 布尔类型
3.9 基本数据类型转换
3.9.1 自动类型转换基础
3.9.2 自动类型转换注意和细节
3.10 强制类型转换
3.10.1 强制转换
3.10.2 强制类型转换细节
3.11 Java_String和基本数据类型的转换
3.11.1 介绍和使用
3.11.2 转换注意事项
4.1.2 算数运算符的使用
4.1.3 取余的技巧
4.1.4 ++技巧
4.1.5 面试题
4.2 关系运算符
4.2.1 关系运算符的介绍
4.2.2 关系运算符的使用
4.3 逻辑运算符
4.3.1 逻辑运算符的介绍
4.3.2 &&和&的使用区别
4.3.5 逻辑运算符练习题
陷进:注意==与=的使用;赋值真结果就为真,赋值假结果就是假;++会改变自身。
4.4 赋值运算符
4.4.1 赋值运算符的介绍
4.4.2 赋值运算符的特点
PS:b+=2会进行自动类型转换,但是b=b+2不会进行类型转换,而是byte类型与一个整型数相加,结果扩大类型成为整型数
4.5 三元运算符
4.5.1 三元运算符的介绍
陷进:++与–位置不同的细节
4.5.2 三元运算符的细节
4.5.3 三元运算符练习题
4.6 运算符优先级
4.7 标识符
4.7.1 标识符命名规则
4.7.2 标识符命名规范
4.8 关键字与保留字
4.8.1 关键字
4.8.2 保留字
4.9 键盘输入语句
4.10 进制
4.10.1 进制介绍
4.10.2 进制的转换
4.10.2.1 其他转十进制
4.10.2.2 十进制转其他
PS:一个字节有八位,这只有六位,要再加两个0
4.10.2.3 二进制转其他
4.10.2.4 其他转二进制
4.11 原码,反码,补码
4.12 位运算符1
PS:原码---->2为int类型,占四个字节,每个字节有八个比特位,0开头表示正数,1代表负数;
操作---->原码->补码->运算(得到的是补码)->转换成原码(注意负数补码转原码的操作)
PS:注意运算半天以后加正负号得到结果
4.13 位运算符2
直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用TOC
语法后生成一个完美的目录。
强调文本 强调文本
加粗文本 加粗文本
标记文本
删除文本
引用文本
H2O is是液体。
210 运算结果是 1024.
7.1 类与对象
7.1.1 类与对象引出
7.1.2 类与关系示意图
7.1.3 快速入门
7.1.4 类与对象的区别和联系
7.1.5 对象在内存中的存在形式 (重要!!!!!)
PS1:new类时,先会把类信息加载到方法区------->然后开始根据属性不同分配不同大小的空间,如果是字符串,分配一个地址,指向常量池,如果是基本数据类型就放堆里------->最后把堆地址返回给cat类
PS2:字符串在堆里存的是地址,存在方法区里一个叫常量池的地方,按照引用方式来存放
7.1.6 属性/成员变量/字段
7.1.7 属性的注意事项和细节说明
7.1.8 创建对象访问机制
7.1.9 内存分配机制
PS:首先在方法区右加载person类信息,然后new在堆里面开空间,有空间就有地址,空间里面的值是默认值,对象创建完成后把堆空间地址返回给p1;下一步找到age赋值,而对于字符串来说,会在方法区左的常量池创建,然后给堆返回创建好的地址
7.1.10 类和对象内存分配机制与流程
7.2 成员方法
7.2.1 方法使用规则和快速入门
7.2.3 成员方法的好处
7.2.4 成员方法的定义
7.2.5 成员方法使用细节
7.2.6 例题
public class test {
public static void main(String[] args) {
AA jud = new AA();
//第一题
if(jud.judge(7)) {
System.out.print("是偶数");
} else {
System.out.print("是奇数");
}
//第二题
jud.print(5,5,'#');
}
}
class AA {
public boolean judge(int num) {
if(num % 2==0)
return true;
else
return false;
// return num % 2 != 0 ? true; false;
}
public void print(int row,int col,char c) {
for(int i = 0; i < row; i++) {
for(int j = 0; j < col; j++) {
System.out.print(c);
}
System.out.println();//换行
}
}
}
7.3 成员方法传参机制(重要!!!!)
7.3.1 基本数据类型传参机制
PS:因为这两个栈是独立的数据空间,而且我是基本数据类型传递的是值,所以互不影响;你形参怎么改变,不会影响到我main方法里的实参
7.3.2 引用数据类型传参机制
PS:引用数据类型会指向堆里的空间,而调用b.test(arr)方法时,arr传递过来的是地址(因为是引用数据类型),那么新栈里arr指向的也是一个地址,指到堆里,然后对新栈的操作其实也是对堆的操作
PS:此时p指向空是指新栈里的p指向了空,不是main栈;而且p=null是指向,不是赋值
public class test {
public static void main(String[] args) {
Person p = new Person();
p.name = "zhang";
p.age = 20;
//创建tools对象
MyTools tools = new MyTools();
Person p2 = tools.copyPerson(p);
System.out.print("p的属性 age=" + p.age + "名字=" + p.name + "\n");
System.out.print("p2的属性 age=" + p2.age + "名字=" + p2.name);
}
}
class Person {
String name;
int age;
}
class MyTools {
//编写一个方法copyPerson,可以复制一个Person对象,返回复制的对象,克隆对象
//注意要求得到新对象和原来的对象是两个独立的对象,只是他们属性相同
//编写方法思路:
//1.方法的返回类型
//2.方法的名字
//3.方法的形参
//4.方法体,创建一个新对象,并复制属性,返回即可
public Person copyPerson(Person p) {
//创建一个新对象
Person p2 = new Person();
p2.name = p.name;
p2.age = p.age;//把原来对象的赋值给新对象
return p2;
}
}
PS:对象里有方法,对象都要new声明,对象通过点引用方法,编写方法有思路,返回方法也要用方法接收
7.4 递归
7.5 方法重载
7.5.1 方法重载的介绍和好处
7.5.2 方法重载快速入门
PS:会自动根据类型选择对应的具体类
7.5.3 方法重载的注意事项和使用细节
7.5.4 方法重载的练习
PS:g大意眼瞎
PS:返回三个数的最大值
7.6 可变参数
7.6.1 可变参数的基本
7.6.2 可变参数的案例
7.6.3 可变参数注意事项和使用细节
public class test {
public static void main(String[] args) {
HspMethod hm = new HspMethod();
System.out.println(hm.showScore("zhuzhu" ,90.1, 65.4));
}
}
class HspMethod {
//分析: 1.方法名 showScore 2.形参 (String.double...) 3.返回 String
public String showScore(String name,double... scores) {
double totalscores = 0;
for(int i=0; i < scores.length; i++) {
totalscores += scores[i];
}
return name + "的" + scores.length + "门课的总分为" + totalscores;
}
}
PS:因为返回是一个字符串,所以就可以被接收
7.7 作用域
7.7.1 基本使用
7.7.2 注意事项和使用细节
7.8.2 快速入门
7.8.3 构造器的注意事项和使用细节
PS:所以在之前还没有学构造器的时候,new一个对象往往只有空括号
PS:首先new person在方法区加载person类,然后在堆里开辟一块空间,创建变量并默认赋值,然后赋给设定的值,这时候才有构造器的处理()内。字符串在常量池里,堆通过地址找字符串,此时才把堆的地址返回给p,p才指向这个空间,所以p只是一个对象引用名
7.10.2 this入门
PS:当前对象就是谁在调用这个构造器,谁就是对象,就是new出来的在这个对象
7.10.3 深入了解this
PS:实际上堆空间默认有一个this指向自己;this.hashCode表示把内存地址用整数表示出来
7.10.4 this的注意事项和使用细节
PS:普通name是就近原则,this.name是访问属性,准确定位
public class test {
public static void main(String[] args) {
Person p1 = new Person("mary", 20);
Person p2 = new Person("jack", 30);
System.out.println("p1和p2比较的结果是" + p1.compareTo(p2));
}
}
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public boolean compareTo(Person p) {
//名字和年龄完全一样
// if(this.name.equals(p.name) && this.age == p.age) {
// return true;
// } else {
// retrun false;
// }
return this.name.equals(p.name) && this.age == p.age;
}
}
PS:对于返回结果接收1或者0的,往往只需要一个语句return+判断语句
public class test {
public static void main(String[] args) {
A01 a01 = new A01();
double[] arr = null;
Double res = a01.max(arr);//返回的是包装类的对象
if(res != null) {
System.out.println("arr的最大值:" + a01.max(arr));
} else {
System.out.println("arr的输入有误");
}
}
}
// 思路分析:
// 1.类名 A01
// 2.方法名 max
// 3.形参 (double[])
// 4.返回值 (double)
// 5.先完成正常的业务,再考虑代码的健壮性,再优化代码
class A01 {
public Double max(double[] arr) {
//如果一个元素都没有/传入null怎么返回呢?注意顺序,注意上面的代码也要改变
if(arr != null && arr.length > 0) {
//null是没有分配地址,[]是分配地址没有值
double max = arr[0];//假定第一个元素是最大的开始
for(int i = 1; i < arr.length; i++) {
if(arr[i] > max) {
max = arr[i];
}
}
return max;
} else {
return null;//用包装类,如果一个都不满足,返回空
}
}
}
public class test {
public static void main(String[] args) {
String[] strs = {"jack", "tom", "jerry", "milan"};
A02 a02 = new A02();
int index = a02.find("hsp", strs);
System.out.println("查找的index=" + index);
}
}
// 思路分析:
// 1.类名 A02
// 2.方法名 find
// 3.形参 (String,String[])
// 4.返回值 (int)
// 5.先完成正常的业务,再考虑代码的健壮性,再优化代码
class A02 {
public int find(String findStr, String[] strs) {
//直接遍历
for(int i = 0; i < strs.length; i++) {
if(findStr.equals(strs[i])) {//对比非数字相等用这个方法
return i;//返回下标
}
}
return -1;
}
}
public class test {
public static void main(String[] args) {
Book book = new Book("笑傲江湖", 200);
book.info();//输出当前情况
book.updatePrice();//更新价格
book.info();
}
}
// 思路分析:
// 1.类名 Book
// 2.属性 Price,name
// 3.方法名 updatePrice
// 4.形参 ()
// 5.返回值 (void)
// 6.提供一个构造器
class Book {
String name;
double price;
public Book(String name, double price) {
this.name = name;
this.price = price;
}
public void updatePrice() {
//如果方法中没有price局部变量,this.price等价于price
if(this.price > 150) {
this.price = 150;
} else if(this.price > 100) {
this.price = 100;
}
}
//显示书籍价格
public void info() {
System.out.println("书名" + this.name + "价格" + this.price);
}
}
8.1 idea
8.1.1 idea介绍
8.1.2 idea使用
public class ArrayTest {
public static void main(String[] args) {
MyTools mt = new MyTools();
int[] arr = {-10 , 7, 87, 5};
mt.bubble(arr);
//引用传递
System.out.println("====排序后的arr====");
for(int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
}
}
class MyTools {
public void bubble(int[] arr) {
//冒泡排序
int temp = 0;
for(int i = 0; i < arr.length; i++) { //外层循环次数-1
for(int j = 0; j < arr.length - 1 - i; j++) {
if(arr[j] > arr[j + 1]) { //交换
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
}
PS:在idea中,当我们run一个文件时,会先编译成.class文件,再运行
PS:俩包不可以同时引入,第一个包引入的话不用加前缀,后面的引用就要加前缀区分
8.2.4 包的命名
8.2.5 常用的包
8.2.6 包的引用
package com.hspedu.pkg;
//建议:需要那个类
import java.util.Scanner;//表示只会引入 java.util 包下的 Scanner 类
import java.util.*;//表示将 java.util 包下的所有类都引入(导入)
public class Import01 {
public static void main(String[] args) {
//使用系统提供的 Array 完成数组排序
int[] arr= {-1, 3, 5, 0};
//传统方法是,自己编写排序(冒泡)
//系统提供了相关类,可以方便完成
Arrays.sort(arr);
//输出
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
}
}
8.3 访问修饰符
8.3.1 访问修饰符规则
8.3.2 访问修饰符注意事项
8.4 封装
8.4.1 封装的介绍
8.4.2 封装的理解和好处
8.4.3 封装实现步骤
8.4.4 快速入门
PS:实现控制私有化;实现判断属性合理性
8.4.5 构造器与setXxx结合
8.4.6 封装课堂练习题
PS:当前运行主类可能是上一个的,此时要先鼠标右键run一次代码,才能用快捷键
8.5.2 继承基本介绍和原理
8.5.3 快速入门
PS:子类一定要加extends,new类一定要写全前缀
PS:当你写了一个构造器,默认的无参构造器就消失了;此时你必须要在子类的每一个构造器中,说明你到底要调用父类的哪一个构造器
8.5.6 继承的本质
PS:当你new时,先加载son的类信息,但是因为son有父类,一直走到了顶级父类object。然后在堆中分配内存空间,同理先加载爷爷的,如果是引用类型的还要放在常量池,依次全部分配。然后把地址分配给main栈里的son引用。son指向这个地址
package com.hspedu.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 = "大头儿子";
}
PS:如果发现age私有,不会上级找age,而是立刻报错终止程序
8.5.7 课堂练习题
第一题:
PS:new了一个对象,要找他的无参构造器;this会调用他的有参构造器;super找它父类的有参构造器;如果他的父类还有继承关系,哪会有一个隐藏的super;然后按父类从大到小输出,再看是从哪来的,是从无参构造器来的,回到那里再按顺序输出,不过只有一条语句可以输出了
第三题:
PS:因为父类自己定义了有参构造器,导致无参构造器消失,而子类继承父类时,要找父类的无参构造器,所以报错,继续构建自己的方法,自动添加父类信息即可
完整代码:
package com.hspedu.extend_;
public class Exercise {
public static void main(String[] args) {
PC pc = new PC("intel", 16, 500, "IBM");
pc.printInfo();
}
}
package com.hspedu.extend_;
//编写computer类,包含CPU、内存、硬盘等属性,getDetails方法用于返回computer的详细信息
public class Computer {
private String cpu;
private int memory;
private int disk;
public Computer(String cpu, int memory, int disk) {
this.cpu = cpu;
this.memory = memory;
this.disk = disk;
}
//返回computer详细信息
public String getDetils() {
return "cpu=" + cpu + " memory=" + memory + " disk=" + disk;
}
public String getCPU() {
return cpu;
}
public void setCPU(String CPU) {
this.cpu = CPU;
}
public int getMemory() {
return memory;
}
public void setMemory(int memory) {
this.memory = memory;
}
public int getDisk() {
return disk;
}
public void setDisk(int disk) {
this.disk = disk;
}
}
package com.hspedu.extend_;
//编写PC子类,继承computer类,添加特有属性【品牌brand】
public class PC extends Computer{
private String brand;
//这里idea,根据继承的规则,自动把构造器的调用写好
//这体现出继承的基本思想:父类的构造器完成父类属性的初始化,子类构造器完成子类属性初始化
public PC(String cpu, int memory, int disk, String brand) {
super(cpu, memory, disk);
this.brand = brand;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public void printInfo() {
System.out.println("PC信息:");
System.out.println(getDetils() + " brand=" + brand);
}
}
8.6 super关键字
8.6.1 基本语法
8.6.2 super使用细节
8.6.3 super和this的比较
8.7.2 注意事项
8.7.3 方法重载和方法重写的比较
8.7.4 课堂练习题
完整代码:
package com.hspedu.test;
public class overrideExercise {
public static void main(String[] args) {
Person jack = new Person("jack", 10);
System.out.println(jack.say());
Student smith = new Student("smith", 20, 123456, 99.8);
System.out.println(smith.say());
}
}
package com.hspedu.test;
public 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=" + name +" age=" + age;
}
}
package com.hspedu.test;
public class Student extends Person{
private int id;
private double score;
public Student(String name, int age, int id, double score) {
super(name, age);//调用父类构造器
this.id = id;
this.score = score;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public String say() { //代码复用
return super.say() + " id=" + id + " score=" + score;
}
}
PS:看似大家都用的是say方法,实际上say已经在父类和子类里面构成了方法重写
8.8 多态
8.8.1 引出问题
PS:每增加一个动物,就要增加一些相似的代码
8.8.2 多态的基本介绍
PS:父类的引用可以指向子类的对象
8.8.3 快速入门
PS:所有具体食物都是Food的子类,所以所有小类型都可以被接收,极大提高代码
8.8.4 多态注意事项和细节讨论-向上转型
PS:在创建编译阶段由编译器用javac,他只认编译类型;但是一旦运行起来就交给java类做了,不关心你的编译类型,所以animal.cat(),只看animal是什么类型,从他开始去找eat方法
8.8.5 多态注意事项和细节讨论-向下转型
PS:animal本来就指向cat,把animal向下转型为cat,用cat类型指向对象,然后编译类型是cat,所以可以调用catchmouse
8.8.7 多态课堂练习
PS:你原来对象引用是指向integer的,你怎么能把integer向下转型成string呢
PS:调用方法看运行内存
PS:先搞清楚,你方法的运行类型是B,所以在子类B的方法里处理
PS:如果子类没有方法sum,那么还是先走子类,发现没有,根据继承机制去找父类,父类的sum方法返回get方法,这个方法在父类和子类上面都有,那么是调用的谁的呢?因为现在在调用方法,我的a的运行类型是B,那么调用的就是B方法,根据动态绑定机制,调用B的get方法,里面方法的属性自然也是用B的
PS:如果子类没有sum方法,那么前面步骤还是一样的,不过变量i用的是A的,因为属性没有动态绑定机制
package com.hspedu.Polyparameter;
public class PloyParameter {
public static void main(String[] args) {
Worker tom = new Worker("tom", 2500);
Manager milan = new Manager("milan",5000, 20000);
PloyParameter ployParameter = new PloyParameter();
ployParameter.showEmpAnnual(tom);
ployParameter.showEmpAnnual(milan);
ployParameter.testWork(tom);
ployParameter.testWork(milan);
}
//实现获取任何员工对象的年工资,并在main方法中调用该方法
public void showEmpAnnual(Employee e) {
System.out.println(e.getAnnual()); //动态绑定机制
}
//添加一个方法,如果是普通员工,则调用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("不做处理...");
}
}
}
package com.hspedu.Polyparameter;
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() + " 正在管理");
}
//重写获取年薪的方法,与员工不同,经理还要加上奖金
@Override
public double getAnnual() {
return super.getAnnual() + bonus;
}
}
package com.hspedu.Polyparameter;
public class Worker extends Employee{
public Worker(String name, double salary) {
super(name, salary);
}
public void work() {
System.out.println("普通员工 " + getName() + " 正在工作");
}
@Override
public double getAnnual() { //因为普通员工没有其他收入,则直接调用父类方法
return super.getAnnual();
}
}
package com.hspedu.Polyparameter;
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;
}
}
8.9 Object类详解
8.9.1 equals方法
PS:怎么查看源码?配置,然后CTRL+b,或者右键->go to->Declaration or Usages
package object_;
public class EqualsExercise01 {
public static void main(String[] args) {
Person person1 = new Person("jack", 10, '男');
Person person2 = new Person("kitty", 10, '男');
//为什么能用equals方法,因为类Person默认继承object
System.out.println(person1.equals(person2));//false,没重写只看对象(地址)是否相等
}
}
class Person{ //extends Object
private String name;
private int age;
private char gender;
//重写Object 的 equals 方法
public boolean equals(Object obj) {
//如果比较的两个对象是同一个对象,则直接返回true
if(this == obj) {
return true;
}
//类型判断
if(obj instanceof Person) { //是Person类,才进行比较
//进行类型转换,向下转型,因为我需要得到obj的各个属性
Person p = (Person)obj;
return this.name.equals(p.name) && this.age == p.age && this.gender == p.gender;
} else {
return false;
}
}
public Person(String name, int age, char gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
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 char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
}
8.9.3 课堂练习
PS: p1.name.equals是字符串,字符串已经把equals内容重写了,它比较的是内容,所以是true;而p1.equals,p1指的是你自己定义的类,他并没有重写equals类,因此这时的equals还是来自他的父类Object,而Object的equals默认判定两个对象是否相等,所以false
8.9.4 hashCode方法
8.9.5 toString方法
package object_;
public class ToString_ {
public static void main(String[] args) {
// Object的toString() 源码
// getClass().getName() 类的全类名(包名+类名)
/*
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
*/
//不重写的情况:
Monster monster = new Monster("小妖怪", "巡山的", 1000);
System.out.println(monster.toString() + " hashcode=" + monster.hashCode());
//当直接输出一个对象时,toString方法会被默认调用:
System.out.println(monster);//等价monster.toString()
}
}
class Monster {
private String name;
private String job;
private double sal;
public Monster(String name, String job, double sal) {
this.name = name;
this.job = job;
this.sal = sal;
}
//重写的情况(输出对象的属性):
//使用快捷键:alt+insert -> toString
@Override
public String toString() { //重写后,一般是把对象的属性输出,也可以自己改
return "Monster{" +
"name='" + name + '\'' +
", job='" + job + '\'' +
", sal=" + sal +
'}';
}
}
8.9.6 finallize方法
package object_;
public class Finalize_ {
public static void main(String[] args) {
Car bmw = new Car("宝马");
//这时car对象就是一个垃圾,垃圾回收器就会回收(销毁)对象,在销毁对象前,会调用该对象的finalize方法
//程序员可以在其中写自己的业务逻辑代码(比如:释放资源,数据库连接,或者打开文件等)
//如果程序员不重写finalize,那么就会调用Object类的finalize,即默认处理
bmw = null;
System.gc();//主动调用垃圾回收器
System.out.println("程序退出了...");
}
}
class Car {
private String name;
//正式应用中,可能有某些属性,资源
public Car(String name) {
this.name = name;
}
//重写finalize:快捷键/直接finalize写+回车
@Override
protected void finalize() throws Throwable {
//super.finalize();
System.out.println("我们销毁了汽车" + name );
System.out.println("释放了某些资源...");
}
}