所有类的基类/超类,一个类没有明确继承的父类,都默认继承Object
判断两个对象内存地址是否相同
public boolean equals(Object obj){
return (this == obj);
}
package com.qf.test01;
public class A {
private String str;
private char c;
private int i;
public A() {
}
public A(String str, char c, int i) {
this.str = str;
this.c = c;
this.i = i;
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public char getC() {
return c;
}
public void setC(char c) {
this.c = c;
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
}
package com.qf.test01;
public class Test01 {
public static void main(String[] args) {
A a1 = new A();
A a2 = new A();
System.out.println(a1 == a2);//引用数据类型使用==是比较内存地址是否相等
System.out.println(a1.equals(a2));
int a = 100;
int b = 200;
System.out.println( a == b);//基本数据类型使用==是比较值是否相等
}
}
获取该类的class对象(class对象作为class文件的访问入口)
package com.qf.test01;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test02 {
public static void main(String[] args) {
A a1 = new A();
A a2 = new A();
Class extends A> c1 = a1.getClass();//获取A类的class对象
Class extends A> c2 = a2.getClass();//获取A类的class对象
System.out.println(c1 == c2);//true
System.out.println("----------");
//获取该类所有的属性
Field[] fields = c1.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("----------");
//获取该类所有的构造方法
Constructor>[] constructors = c1.getDeclaredConstructors();
for (Constructor> constructor : constructors) {
System.out.println(constructor);
}
System.out.println("----------");
//获取该类所有的方法
Method[] methods = c1.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
}
}
获取到对象的hash值(hash值 - 内存地址+散列算法,hash值不等于内存地址)
package com.qf.test01;
public class Test03 {
public static void main(String[] args) {
A a1 = new A();
A a2 = new A();
System.out.println(a1.hashCode()); //获取a1的哈希值
System.out.println(a2.hashCode()); //获取a1的哈希值
}
}
获取对象的字符串形式(将对象转换为字符串)
public String toString(){
//getClass().getName() - 获取class对象的名字(类的全路径-报名+类名)
//Integer.toHexString(hashCode()) - 获取对象的hash值的十六进制表示(hash值原本是十进制)
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
package com.qf.test01;
public class Test04 {
public static void main(String[] args) {
A a1 = new A();
//com.qf.test01.A @ 15db9742
System.out.println(a1);//打印对象,默认调用toString()
System.out.println(a1.toString());
}
}
所有的类都直接或间接继承Object,所以所有的类都能使用Object里的方法
含义:比较两个对象的内存地址是否相同
标杆作用:比较两个对象是否相同,但是不同的子类判断两个对象是否相同规则是不一样的,所以在子类中重写equals方法即可
package com.qf.test02;
public class User {
private String username;
private String password;
private double money;
public User() {
}
public User(String username, String password, double money) {
this.username = username;
this.password = password;
this.money = money;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
@Override
public boolean equals(Object obj) {
//先判断两个对象的地址是否相同,地址都相同,证明是同一个对象
if(this == obj){
return true;
}
//判断两个用户对象的账号是否相同
User user = (User) obj;//父类转子类:向下转型
if(this.username.equals(user.username)){//equals-是String类重写Object类的equals方法(表示比较两个字符串内容是否相同)
return true;
}
return false;
}
@Override
public String toString() {
return this.username + " -- " + this.password + " -- " + this.money;
}
}
含义:获取对象的字符串表示 -- getClass().getName() + "@" + Integer.toHexString(hashCode());
标杆作用:获取对象的字符串表示,但是不同的子类有不同的属性(数据),所以在子类中重写toString方法即可
目的:打印对象,输出对象中所有的属性,方便查看数据
需求1:模拟银行用户
package com.qf.test02;
public class Test01 {
public static void main(String[] args) {
User user1 = new User("1445584980", "123123", 1000);
User user2 = new User("1445584980", "123123", 1000);
System.out.println(user1.equals(user2));//true
System.out.println(user1);//默认调用toString
System.out.println(user2);//默认调用toString
}
需求2:默认学生用户
package com.qf.test02;
public class Student {
private String name;
private char sex;
private int age;
private String classId;//班级号
private String id;//学号
public Student() {
}
public Student(String name, char sex, int age, String classId, String id) {
this.name = name;
this.sex = sex;
this.age = age;
this.classId = classId;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getClassId() {
return classId;
}
public void setClassId(String classId) {
this.classId = classId;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public boolean equals(Object obj) {
//先判断两个对象的地址是否相同,地址都相同,证明是同一个对象
if(this == obj){
return true;
}
//判断两个学生对象的班级号+学号是否相同
Student stu = (Student) obj;父类转子类:向下转型
if(this.classId.equals(stu.classId) && this.id.equals(stu.id)){
return true;
}
return false;
}
@Override
public String toString() {
return "Student [name=" + name + ", sex=" + sex + ", age=" + age + ", classId=" + classId + ", id=" + id + "]";
}
}
package com.qf.test02;
public class Test01 {
public static void main(String[] args) {
Student stu1 = new Student("李伟杰", '男', 18, "2204", "001");
Student stu2 = new Student("李伟杰", '男', 18, "2204", "001");
System.out.println(stu1.equals(stu2));//true
System.out.println(stu1);//默认调用toString
System.out.println(stu2);//默认调用toString
}
}
注意:String-字符串,底层使用字符数组存储数据
1.先判断内存地址
1.1 内存地址相同 -- 返回 true
1.2 内存地址不相同
2.获取对象的字符数组,判断长度是否一致
2.1 长度不一致 -- 返回false
2.2 长度一致
3.循环遍历字符数组,比较ASCII码
3.1 ASCII不相同 -- 返回false
3.2 遍历后,所有的ASCII都相同 -- 返回true
package com.qf.test03;
public class MyString {
private char[] value;//字符串底层容器
public MyString(String original){
value = original.toCharArray();//将字符串转换为字符数组,再赋值给value
}
@Override
public boolean equals(Object obj) {
if(this == obj){
return true;
}
MyString m = (MyString) obj;//Test01类中的m2
char[] v1 = this.value;//m1中的char[] -- ['a','b','c']
char[] v2 = m.value;//m2中的char[] -- ['a','b','c']
if(v1.length == v2.length){//两个字符数组长度一致
for (int i = 0; i < v1.length; i++) {
if(v1[i] != v2[i]){//判断的是字符的ASCII码
return false;
}
}
return true;
}
return false;
}
@Override
public String toString() {
return String.valueOf(value);//把字符数组转换为字符串
}
}
package com.qf.test03;
public class Test01 {
public static void main(String[] args) {
String str1 = new String("abc");
String str2 = new String("abc");
System.out.println(str1 == str2);//false - 比较的是内存地址
System.out.println(str1.equals(str2));//true - 调用String类重写的equals方法 - 比较的是字符串内容
System.out.println(str1);//默认调用toString
System.out.println(str2);//默认调用toString
System.out.println("----------------");
MyString m1 = new MyString("abc");
MyString m2 = new MyString("abc");
System.out.println(m1 == m2);//false - 比较的是内存地址
System.out.println(m1.equals(m2));//true - 调用MyString类重写的equals方法 - 比较的是字符串内容
System.out.println(m1);//默认调用toString
System.out.println(m2);//默认调用toString
}
}
作用:
1.修饰类:该类不能被继承
2.修饰方法:该方法不能被重写
3.修饰变量:该变量变成常量,不能被重新赋值
使用final修饰的变量(常量)存在常量池中
直到项目结束(main方法结束),常量才会被回收
所以常量被其他的变量生命周期更长
常量的命名规范:所有字母都大写,单词与单词之间使用下划线隔开
package com.qf.test04;
//最终的类,不能被继承
//public final class Father {
public class Father {
//最终的方法,不能被子类重写
//public final void method(){}
public void method(){}
}
package com.qf.test04;
public class Son extends Father{
@Override
public void method() {
//最终的变量 -- 常量,不允许重新赋值
//final int I = 100;
//System.out.println(I);
final int I;
I = 100;
System.out.println(I);
}
}
package com.qf.test04;
public class Test01 {
public static void main(String[] args) {
Son son = new Son();
son.method();
}
}
编写人类、中国人、日本人类,操作对象
分析:
人类:
属性:姓名、性别、年龄
方法:吃饭饭、睡觉觉
中国人类 继承 人类:
属性:身份证
方法:打太极
日本人类 继承 人类:
属性:年号
方法:拍电影
需求的场景:三个类都是一个人写的
package com.qf.test05;
public abstract class Person {
private String name;
private char sex;
private int age;
public Person() {
}
public Person(String name, char sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//抽象方法
//该方法应该在该类里,但是又不好实现,所以把该方法设置为抽象方法,交给非抽象的子类去实现
public abstract void eat();
public void sleep(){
System.out.println(this.name + "睡觉觉");
}
}
package com.qf.test05;
public abstract class Chinese extends Person{
private String id;
public Chinese() {
}
public Chinese(String name, char sex, int age, String id) {
super(name, sex, age);
this.id = id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public abstract void hobby();
}
package com.qf.test05;
public class SiChuan extends Chinese{
public SiChuan() {
}
public SiChuan(String name, char sex, int age, String id) {
super(name, sex, age, id);
}
@Override
public void hobby() {
System.out.println(super.getName() + "喜欢打麻将、砸金花、斗牛牛");
}
@Override
public void eat() {
System.out.println(super.getName() + "吃火锅、烧烤、串串香");
}
}
package com.qf.test05;
public class GuangDong extends Chinese{
public GuangDong() {
}
public GuangDong(String name, char sex, int age, String id) {
super(name, sex, age, id);
}
@Override
public void hobby() {
System.out.println(super.getName() + "喜欢做生意");
}
@Override
public void eat() {
System.out.println(super.getName() + "吃肠粉、潮汕牛肉火锅");
}
}
package com.qf.test05;
public class Japanese extends Person{
private String yearNum;
public Japanese() {
}
public Japanese(String name, char sex, int age, String yearNum) {
super(name, sex, age);
this.yearNum = yearNum;
}
public String getYearNum() {
return yearNum;
}
public void setYearNum(String yearNum) {
this.yearNum = yearNum;
}
@Override
public void eat() {
System.out.println(super.getName() + "吃马赛克...");
}
}
package com.qf.test05;
public class Test01 {
public static void main(String[] args) {
Japanese j = new Japanese("波多野结衣", '女', 16, "昭和");
j.eat();
System.out.println("-------");
SiChuan sc = new SiChuan("李伟杰", '男', 18, "1234567890");
sc.eat();
sc.hobby();
System.out.println("-------");
GuangDong gd = new GuangDong("李嘉诚", '男', 85, "0987654321");
gd.eat();
gd.hobby();
}
}
1.抽象类不能有构造方法?
抽象类可以有构造方法
2.抽象类中只能有抽象方法?
抽象类中可以有非抽象方法(构造方法、成员方法和静态方法)
3.抽象类中不可以没有抽象方法?
抽象类中可以没有抽象方法,但是毫无意义
4.如果父类是抽象类,则子类必须实现父类的抽象方法?
不一定,子类如果是抽象类,可以不实现父类的抽象方法
5.可以使用new关键字来创建抽象类对象?
不可以,抽象类是不能有对象的,创建的是匿名内部类的对象
1.底层创建了匿名类,继承Person类,重写eat()
2.创建匿名类的对象
3.将匿名类的对象的内存地址赋值给父类的引用-p
package com.qf.test05;
public class Test02 {
public static void main(String[] args) {
Person p = new Person() {
@Override
public void eat() {
System.out.println(super.getName() + "xxx");
}
};
p.eat();
}
}
接口是特殊的抽象类,接口中只能有静态常量和抽象方法
JDK1.8的新特性:接口中可以有静态方法和默认方法
应用场景:接口是一个标准,规定实现类应该要完成的方法
1.接口中的抽象方法默认使用public abstract修饰
2.接口中的属性默认使用public static final修饰
编写学生管理系统
分析:
该系统管理学生 -- 增删改查
package com.qf.test06;
public class Student {
private String name;
private char sex;
private int age;
private String classId;//班级号
private String id;//学号
public Student() {
}
public Student(String name, char sex, int age, String classId, String id) {
this.name = name;
this.sex = sex;
this.age = age;
this.classId = classId;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getClassId() {
return classId;
}
public void setClassId(String classId) {
this.classId = classId;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public boolean equals(Object obj) {
//先判断两个对象的地址是否相同,地址都相同,证明是同一个对象
if(this == obj){
return true;
}
//判断两个学生对象的班级号+学号是否相同
Student stu = (Student) obj;父类转子类:向下转型
if(this.classId.equals(stu.classId) && this.id.equals(stu.id)){
return true;
}
return false;
}
@Override
public String toString() {
return "Student [name=" + name + ", sex=" + sex + ", age=" + age + ", classId=" + classId + ", id=" + id + "]";
}
}
package com.qf.test06;
//学生管理系统的接口
public interface StudentManagerSystem {
int NAME = 1;
int SEX = 2;
int AGE = 3;
int CLASS_ID = 4;
int ID = 5;
/**
* 添加学生
* @param stu 目标学生
* @return 状态码
*/
public int add(Student stu);
/**
* 学生容器的扩容
*/
public void expansion();
/**
* 删除学生
* @param classId 班级号
* @param id 学号
* @return 状态码
*/
public int delete(String classId,String id);
/**
* 修改学生信息
* @param classId 班级号
* @param id 学号
* @param type 修改的类型(1-姓名 2-性别 3-年龄 4-班级号 5-学号)
* @param val 要修改的值
* @return 修改是否成功
*/
public boolean update(String classId,String id,int type,Object val);
/**
* 修改学生姓名
* @param classId 班级号
* @param id 学号
* @param name 要修改的值
* @return 修改是否成功
*/
public boolean updateName(String classId,String id,String name);
/**
* 修改学生性别
* @param classId 班级号
* @param id 学号
* @param sex 要修改的值
* @return 修改是否成功
*/
public boolean updateSex(String classId,String id,char sex);
/**
* 修改学生年龄
* @param classId 班级号
* @param id 学号
* @param age 要修改的值
* @return 修改是否成功
*/
public boolean updateAge(String classId,String id,int age);
/**
* 修改学生班级号
* @param classId 班级号
* @param id 学号
* @param targetClassId 要修改的值
* @return 修改是否成功
*/
public boolean updateClassId(String classId,String id,String targetClassId);
/**
* 修改学生学号
* @param classId 班级号
* @param id 学号
* @param targetId 要修改的值
* @return 修改是否成功
*/
public boolean updateId(String classId,String id,String targetId);
/**
* 查询学生
* @param classId 班级号
* @param id 学号
* @return 在容器中的下标
*/
public int query(String classId,String id);
/**
* 查询学生
* @param name 姓名
* @return 学生数组
*/
public Student[] queryByName(String name);
/**
* 查询学生
* @param sex 性别
* @return 学生数组
*/
public Student[] queryBySex(char sex);
/**
* 查询学生
* @param startAge 开始年龄(包含)
* @param endAge 结束年龄(不包含)
* @return 学生数组
*/
public Student[] queryByAge(int startAge,int endAge);
/**
* 查询学生
* @param classId 班级号
* @return 学生数组
*/
public Student[] queryByClassId(String classId);
/**
* 查询学生
* @param classId 班级号
* @param id 学生号
* @return 学生对象
*/
public Student queryByClassIdAndId(String classId, String id);
/**
* 打印容器内的所有学生对象
*/
public void printStuInfo();
/**
* 传入数组打印学生
* @param stus 学生数组
*/
default void printStuInfo(Student[] stus){
for (Student stu : stus) {
System.out.println(stu);
}
}
}
package com.qf.test06;
//学生管理系统的实现类
public class StudentManagerSystemImpl implements StudentManagerSystem{
@Override
public int add(Student stu) {
// TODO Auto-generated method stub
return 0;
}
@Override
public void expansion() {
// TODO Auto-generated method stub
}
@Override
public int delete(String classId, String id) {
// TODO Auto-generated method stub
return 0;
}
@Override
public boolean update(String classId, String id, int type, Object val) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean updateName(String classId, String id, String name) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean updateSex(String classId, String id, char sex) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean updateAge(String classId, String id, int age) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean updateClassId(String classId, String id, String targetClassId) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean updateId(String classId, String id, String targetId) {
// TODO Auto-generated method stub
return false;
}
@Override
public int query(String classId, String id) {
// TODO Auto-generated method stub
return 0;
}
@Override
public Student[] queryByName(String name) {
// TODO Auto-generated method stub
return null;
}
@Override
public Student[] queryBySex(char sex) {
// TODO Auto-generated method stub
return null;
}
@Override
public Student[] queryByAge(int startAge, int endAge) {
// TODO Auto-generated method stub
return null;
}
@Override
public Student[] queryByClassId(String classId) {
// TODO Auto-generated method stub
return null;
}
@Override
public Student queryByClassIdAndId(String classId, String id) {
// TODO Auto-generated method stub
return null;
}
@Override
public void printStuInfo() {
// TODO Auto-generated method stub
}
}