目录
内容概括
- 访问权限:protected
- 关键字:final
- 祖先类:Object(最顶级父类)
心情感悟
感觉今天的节奏最好了,可能是学的比较少,上午学新知识,下午一直做练习。
知识点相对较少,也更有信心把握。
知识点
访问权限:protected
1、定义:
- 用来声明可以挎包调用的方法
2、性质、要求:
- 跨包调用的两个类必须是父类和子类关系
- 在子类调用父类方法时要创建子类对象调用,不是创建父类对象调用。
例:
//一个包
package com.jsoft.morning;
//父类
public class Ch01 {
protected void show(){
}
public void info(){
}
}
//另一个包
package com.jsoft.afternoon;
import com.jsoft.morning.Ch01;
//子类
public class Demo extends Ch01{
public static void main(String[] args) {
//定义父类对象调用父类方法,报错
Ch01 ch01 = new Ch01();
ch01.show();//报错
//定义子类对象调用父类方法,不报错,只能调用protected声明的方法
Demo demo = new Demo();
demo.show();
demo.info();//报错
}
}
关键字:final
final关键字:最终的,终极的
final可以修饰的结构
1.类:public final class
final修饰的类是终极类、最终类,没有任何类可以继承final修饰的类
工具类都是final修饰的类,String、Math2.属性:private final String name
final修饰的属性是常量,不可以改变的
常量的命名规则:单词的所有字母大写,如果名字是多个单词,用下划线分割。
常量不能只声明,不赋值。必须有初始值(null也得写出来)
如例一
3.方法:private final void show
final修饰的方法不可以被重写
如例二
例一:
private final String EMPLOYEE_NAME = "哈哈";
public Ch02(String name){
this.name = name ;//报错了
}
例二:
//父类:
public class Father {
public final void show(){
}
public void info(){
}
}
//子类:
public class Ch02 extends Father{
public void show(){}//报错了
}
final修饰的类中是不是一定要有常量?
不是,可以没有常量
final修饰类、常量、方法没有联系
构造器:public 直接加名为构造器
其他的都不是构造器(例如:public void Ch02(),不是构造器,只是特殊的方法)
方法的重写注解:
注解(@ override):代表这个方法是从父类重写过来的
以后重写方法时加上。
祖先类:Object(最顶级父类)
定义:如果一个类没有明确的写出父类,那它的父类就是Object(默认继承),所以Object是所有类的直接或间接父类。
拓展:带包的路径的类名叫全类名。
Object类中的方法
Object类中有11个方法,用到的不多
1.hashCode():
1、它的返回值实际上就是对象运行时的内存地址
2、hash算法:一般翻译为“散列”,把任意长度的输入,通过一个散列算法变换成固定长度的输出,输出的结果为散列值(hash值)。
(1)hash算法可以用来检验文件完整性:
- 下载文件时断网,怎么知道下没下完?
- 文件下载99%时,会卡更长时间,此时文件已经下载完成,只不过在检验文件完整性
(2)hash算法的密码加密:
- MD5加密。可以生成64位散列值,不可逆
- SHA家族,比MD5强。可以生成256位散列值。
2.equals():
定义:和 == 没区别,比较地址。
存在意义:为了让子类重写例:有两个数据:
Person p1 = new Person("张三","220322200103255555"); Person p2 = new Person("张三","220322200103255555");
他们本质上是一个人,但是由于存储地址不同,比较时输出结果为false(不是同一个人),这时“==”改变不了结果,需要进行对方法的重写:
public class Person {
private String name;
private String cardId;
public Person(String name, String cardId) {
this.name = name;
this.cardId = cardId;
}
@Override
public boolean equals(Object obj){
Person person = (Person) obj;
//当方法调用者的身份证号和参数的身份证号相同,则认为是同一个人
if (this.cardId.equals(person.cardId)){
return true;
}
return false;
}
}
3.toString():
定义:转换成字符串
存在意义:为了让子类重写例:当我们直接输出一个对象时,输出的是它的虚地址,可以重写toString方法,输出字符串
4.finalize():
垃圾回收方法
5.clone():
克隆,必须实现Cloneable窗口
面试题
遗留问题:Integer
在Integer的内部,有一个缓冲区,把byte(-128~127)范围内的数,缓存起来,
在这个范围用==比较两个Integer得到true,范围外false,一般淘汰==,用equals().
练习1
需求: 信息录入: 1、录入老师信息:身份证号相同的就是一个人(有提示),重写toString方法 老师信息:姓名,省份证号,工号,年龄 2、录入学生信息:身份证号相同的就是一个人(有提示),重写toString方法 学生信息:姓名,身份证号,学号,年龄 一个老师教多个学生 分析:学生是老师的属性 1、老师类中,有teach方法,最终会展示出他教哪些学生 2、学生类中:有一个study方法,最终会展示他跟哪位老师学习 3、学校类中:有很多老师,很多学生,最终会展示出有哪些老师,哪些学生。 在Demo中的测试相关功能 1.创建一个老师,再来一个老师比较一下 2.学生比较。 3.老师教的学生的信息
School类
public class School {
//定义存储老师的数组
private Teacher [] teachers;
//定义存储学生的数组
private Student [] students;
public Teacher[] getTeacher() {
return teachers;
}
public void setTeachers(Teacher[] teachers) {
this.teachers = teachers;
}
public Student[] getStudents() {
return students;
}
public void setStudents(Student[] students) {
this.students = students;
}
public void showTeacher(){
// 老师和他对应的学生的信息
for (Teacher teacher : teachers) {
System.out.println(teacher.teach());
}
}
public void showStudents() {
// 学生和他对应的老师的信息
for (Student student : students) {
System.out.println(student.study());
}
}
}
Person类
public class Person {
private String name;
private Integer age;
private String cardId;
@Override
public boolean equals(Object obj) {
Person person = (Person) obj;
// 当方法调用者的身份证号和参数的身份证号内容相同,则认为是同一个人
if (this == person){
return true;
}
if(this.cardId.equals(person.cardId)){
return true;
}
return false;
}
//输出姓名,年龄,身份证号
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", cardId='" + cardId + '\'' +
'}';
}
//给人定义初始值
public Person(String name, Integer age, String cardId) {
this.name = name;
this.age = age;
this.cardId = cardId;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getCardId() {
return cardId;
}
public void setCardId(String cardId) {
this.cardId = cardId;
}
}
Student类
public class Student extends Person{
private String stuNum;
private Teacher teacher;
public Student() {
}
public Student(String name, Integer age, String cardId, String stuNum, Teacher teacher){
super(name, age, cardId);
this.stuNum = stuNum;
this.teacher = teacher;
}
//重写:输出人的属性之外,加上学生的属性:学号
@Override
public String toString() {
return super.toString()+"Student{" +
"stuNum='" + stuNum + '\'' +
'}';
}
//this代表本类对象:tostring
//在tostring输出的结果上,加上学生的属性:老师是谁
public String study(){
return this +"老师是:" + teacher;
}
public String getStuNum() {
return stuNum;
}
public void setStuNum(String stuNum) {
this.stuNum = stuNum;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
}
Teacher类
public class Teacher extends Person{
//工号
private String teaNum;
//所教学生
private Student []stus;
public Teacher() {
}
//给老师定义初始值
public Teacher(String name,Integer age, String cardId, String teaNum){
super(name, age, cardId);
this.teaNum = teaNum;
}
//在重写的tostring输出结果基础上。加上老师的属性:所教学生
public String teach(){
//教哪些学生
return this.toString() + ",\n" + Arrays.toString(stus);
}
public String getTeaNum() {
return teaNum;
}
public void setTeaNum(String teaNum) {
this.teaNum = teaNum;
}
public Student[] getStus() {
return stus;
}
public void setStus(Student[] stu) {
this.stus = stu;
}
//重写:在人的属性基础上。加上老师的属性:工号
@Override
public String toString() {
return super.toString()+"Teacher{" + "teaNum='" + teaNum;
}
}
Demo类(测试代码)
public class Demo {
public static void main(String[] args) {
//定义老师:
Teacher teacher = new Teacher("xyz",40,"789789","8001");
//定义学生
Student s1 = new Student("aaa",20,"123456","1001",teacher);
Student s2 = new Student("bbb",20,"123457","1002",teacher);
Student s3 = new Student("ccc",20,"123458","1003",teacher);
Student s4 = new Student("ddd",20,"123459","1004",teacher);
Student s5 = new Student("eee",20,"123450","1005",teacher);
//储存学生
Student [] stus = new Student[]{s1,s2,s3,s4,s5};
teacher.setStus(stus);
Teacher teacher1 = new Teacher("qwer",40,"456456","8002");
Student s6 = new Student("fff",22,"223456","2001",teacher1);
Student s7 = new Student("ggg",22,"223457","2002",teacher1);
Student s8 = new Student("hhh",22,"223458","2003",teacher1);
Student s9 = new Student("iii",22,"223459","2004",teacher1);
Student s10 = new Student("jjj",22,"223450","2005",teacher1);
Student [] stus1 = new Student[]{s6,s7,s8,s9,s10};
teacher1.setStus(stus1);
//储存所有老师、学生
Teacher [] teacherz = new Teacher[]{teacher,teacher1};
Student [] studentz = new Student[]{s1,s2,s3,s4,s5,s6,s7,s8,s9,s10};
//显示所有师生信息
School school = new School();
school.setTeachers(teacherz);
school.setStudents(studentz);
school.showStudents();
school.showTeachers();
}
}
练习2
封装一个超级数组。包括好多方法,完成以下要求:
1、创建这个超级数组的时候,不需要指定长度。
2、添加数据
3、在指定位置添加数据
4、删除数据
5、删除指定位置的数据
6、修改数据
7、获取指定位置的数据
8、获取数组的长度
9、判断是否超出边界
10、扩容
超级数组类
public class SuperArray {
// 维护一个数组,要考虑的是怎么存
private Integer [] array;
// 超级数组的长度
private int size;
// 数组当前的容量
private int capacity;
//定义超级数组初始长度
public SuperArray(){
array = new Integer[10];
capacity = 10;
}
public SuperArray(int capacity){
array = new Integer[capacity];
this.capacity = capacity;
}
// 添加数据,默认添加,在数组的尾部添加
public void add(Integer data) {
// 添加时要确保容量足够,如果不够,就需要扩容
ensureCapacity(size + 1);
// 真正的添加数据
array[size++] = data;
}
// 添加数据,传入两个参数
// 在指定位置添加
public void add(int index,Integer data){
if(rangeCheck(index)){
ensureCapacity(size + 1);
System.arraycopy(array,index,array,index + 1,size - index);
// 真正的添加数据
array[index] = data;
size++;
}
}
public void del(){
size--;
}
public void del(int index){
if(rangeCheck(index)){
array[index] = 0;
for (int i = 0; i < array.length - index - 1; i++) {
array[index + i] = array[index + 1 + i];
}
size -= 1;
}
}
public void change(Integer index,Integer data){
array[index] = data;
}
// 获取超级数组的长度
public int size(){
return size;
}
// 获取指定下标的元素
public Integer get(int index) {
// 判断一下index和合法性
if(rangeCheck(index)){
return array[index];
}
return null;
}
private boolean rangeCheck(int index) {
// index >= 0
// index <= size - 1
return (index >=0 && index <= size - 1);
}
// 这个方法只在当前类使用,所以声明成private
private void ensureCapacity(int needCapacity) {
if(needCapacity > capacity){
// 1.5倍
capacity = capacity + (capacity >> 1);
// 创建一个新的扩容好的数组
Integer [] newArray = new Integer[capacity];
// 把原数组的数据拷贝过来
/*
src:原数组
srcPos:拷贝原始数组的起始位置
dest:目标数组
destPos:目标数组的起始位置
length:拷贝数据的长度
*/
System.arraycopy(array,0,newArray,0,array.length);
array = newArray;
}
}
}
Test类(测试代码)
public class Test {
public static void main(String[] args) {
// 创建一个超级数组的对象
SuperArray superArray = new SuperArray(5);
superArray.add(20);
superArray.add(10);
superArray.add(70);
superArray.add(90);
superArray.add(50);
//添加数据
superArray.add(1,100);
for (int i = 0; i < superArray.size(); i++) {
System.out.println(superArray.get(i));
}
}
}
public class Test {
public static void main(String[] args) {
// 创建一个超级数组的对象
SuperArray superArray = new SuperArray(5);
superArray.add(20);
superArray.add(10);
superArray.add(70);
superArray.add(90);
superArray.add(50);
//删除数据
superArray.del();
for (int i = 0; i < superArray.size(); i++) {
System.out.println(superArray.get(i));
}
}
}
public class Test {
public static void main(String[] args) {
// 创建一个超级数组的对象
SuperArray superArray = new SuperArray(5);
superArray.add(20);
superArray.add(10);
superArray.add(70);
superArray.add(90);
superArray.add(50);
//改变数据
superArray.change(2,500);
for (int i = 0; i < superArray.size(); i++) {
System.out.println(superArray.get(i));
}
}
}