JAVA学习笔记——第七章 面向对象中级(一)

🔥博客主页: A_SHOWY
🎥系列专栏力扣刷题总结录 数据结构  云计算  数字图像处理  力扣每日一题_ 

 1.关于IDEA

1.1 IDEA目录

Idea的项目编译后,其class文件会存在out文件重,src存放源文件。

1.2 快捷键 

  1. 删除当前行:CTRL + Y
  2. 复制当前行: CTRL + D
  3. 添加注释:CTRL + /
  4. 自动导入需要的类:ALT + ENTER   
  5. 快速格式化:CRTL + Alt  + L(可能会锁住QQ)
  6. 快速运行: Alt + Shift + F10
  7. 创建构造器:Alt + insert
  8. 查看一个类的层级关系:CTRL + H
  9. 光标放在方法上,CTRL + B,可以定位到哪个类的方法
  10. 自动分配变量名,在后边加.var

1.3 模板/自定义模板

  1.  main:直接输出 public static void main(String[] args)
  2. sout:输出模板
  3. fori:循环模板

2.包 

2.1 作用 

  1. 区分相同名字的类
  2. 类很多的时候,可以很好的管理类
  3. 控制访问范围 

2.2 基本语法 

package(关键字,表示打包)  com.hspedu(表示包名)

2.3 包的本质分析

包的本质是创建不同文件夹保存类文件

2.4 例子:

package com.test;

import com.xiaoming.Dog;//默认是小明

public class reDog {
    public static void main(String[] args) {
        Dog dog = new Dog();
        System.out.println(dog);
        com.xiaoqiang.Dog dog1 = new com.xiaoqiang.Dog();
        System.out.println(dog1);
    }
}

2.5 包的命名

规则:只能包含数字字母下划线小圆点,但是不能数字开头,不能关键字保留字

规范:com.公司名.项目名.模块名

2.6常用的包

2.7 如何导入包

建议需要使用到哪个就导入哪个

import java.util.Scanner;//导入一个类
import java.util.*;//表示将util包下的所有类都导入

用一下utils里面的array(排序)

package com.test;
import java.util.Arrays;

public class reDog {
    public static void main(String[] args) {
        int[] arr = {1,5,3,2,84,35};
        Arrays.sort(arr);
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

细节

package的作用是声明当前类所在的包,需要放在类的最上面,一个类中只能有一个package,那些import导入放到package的下面

3.访问修饰符 

四种访问控制修饰符,用来控制方法和属性的访问权限(范围)

  1. 公开级别:public修饰,对外公开
  2. 受保护基本:protected,对子类和同一个包中的类公开
  3. 默认级别:没有修饰符号,向同一个包的类公开
  4. 私有级别:private,只有类本身可以访问

3.1 注意事项 

  1. 修饰符可以修饰类中的属性、成员方法和类
  2. 只有默认和public才能修饰类,遵循上述表

4.面向对象编程的三大特征

 封装继承和多态(重点  +  难度)

4.1 封装(encapsulation)

把抽象出的数据(属性)和对数据的操作(方法)封装在一起,数据被保护在内部,程序其他部分只有通过被授权的操作【方法】才能对数据进行操作。

好处

  1.  隐藏实现的细节  方法<--调用

  2. 可以对数据进行验证,保证安全和合理性

步骤 

  1. 对属性进行私有化
  2. 提供一个公共的方法(public)set方法,用于对属性的判断并且赋值,public void setXXX(类型参数名),可以加入数据验证的业务逻辑
  3. 提供一个公共的get方法,用于获取属性的值public XX getXXX(){//权限判断  return XX;}

案例 

快速getset方法:alt + insert 

package encape;

import java.sql.SQLOutput;
import java.util.Scanner;

public class encapsolution1 {
    public static void main(String[] args) {
        Person person = new Person();
//        person.name = "jack";
//        person.age = 3000;错误
        person.setName("jackeda");
        person.setAge(300);
        person.setSalary(8000.0);
        System.out.println(person.info());
        System.out.println(person.getSalary());
    }
}

class Person{
    public String name;//名字公开
    private int age;//年龄私有化
    private double salary;//工资私有化
//    public void setName(){
//        this.name = name;
//    }
//    public String getName(){
//        return name;
//        自己写setget方法太慢,快捷键,然后根据要求完善代码

    public String getName() {
        return name;
    }

    public void setName(String name) {
        if(name.length() >= 2 && name.length() <= 6){
        this.name = name;}
    else{
            System.out.println("名字长度不对,2-6长度");
        }
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if(age >= 1 && age <= 120){
        this.age = age;}
         else {
            System.out.println("年龄需要在1-120之间,给默认年龄18");
           this.age = 18;//给一个默认年龄
        }
    }

    public double getSalary() {
//        设置一个密码
        System.out.println("请输入密码");
        Scanner scanner = new Scanner(System.in);
        if(scanner.next().equals("88918876"))
        {return salary;}
        else {System.out.println("密码错误");
        return 0; }
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
//    写一个方法返回属性信息
    public String info(){
        return "信息为 name = " + name + " age = " + age + " salary = " + salary;
}
}

构造器和封装 

 如果设置构造器的话,是不是就相当于破解了我们的加密机制,所以在构造器中设置set方法进行判断。可以有效的限制数据。


public class encapsolution1 {
    public static void main(String[] args) {
        Person person1 = new Person("smith",2000,8600);
        System.out.println(person1.info());
    }
}

class Person{
    public Person() {
    }
//在构造器里面搞一个set方法判断
    public Person(String name, int age, double salary) {
//        this.name = name;
//        this.age = age;
//        this.salary = salary;
        setSalary(salary);
        setAge(age);
        setName(name);
    }
}

4.2 继承(extends)

问题

两个类的属性和方法有很多是相同的,代码复用较多,较为冗余  =》继承,当多个类 存在相同的属性和方法的时候,可以从这些类中抽象出父类,在父类中定义相同的属性和方法,只需要通过extends声明继承父类即可。 A类就叫父类(基类),B类、C类为子类(派生类)

 语法

class 子类 extends 父类{},子类会自动拥有父类定义的属性和方法

实例 :继承机制解决代码冗余

 

//extends01
package com.jicheng;

public class extends01 {
    public static void main(String[] args) {
        Pupil pupil = new Pupil();
        pupil.name = "银角大王";
        pupil.age = 15;
        pupil.testing();
        pupil.setScore(60);
        pupil.showInfo();
        System.out.println("===============");
        Graduate graduate = new Graduate();
        graduate.name = "金角大王";
        graduate.age = 22;
        graduate.setScore(59);
        graduate.showInfo();
    }
}


//Graduate
package com.jicheng;

public class Graduate extends Student {
    public void testing(){
        System.out.println("大学生"  + name + "正在考小写数学");
    }
}


//Pupil
package com.jicheng;

public class Pupil extends Student {
    public void testing(){
        System.out.println("小学生" + name + "正在考小写数学");
    }
}


//Student
package com.jicheng;

public class Student {
//共有属性
    public String name;
    public int age;
    public double score;
//共有方法
    public void setScore(double score){
        this.score = score;
    }

    public void showInfo(){
        System.out.println("学生名" + name + "年龄" + age + "成绩" + score);
    }
}

 细节

  1. 子类继承了父类的所有方法和属性,但是私有属性不能在子类中直接访问,要通过父类提供的公共的方法去访问 例如
    //对于私有属性和私有方法
    //在父类中
    class Fulei{
    private n4;
    public getn4(){
    return n4;
    }
    
    private test400(){
    System.out.println("test400");
    }
    public void callTest400(){
         test400();
    }
    }
    
    //子类中
    class Zilei extends Fulei{
    System.out.println(getn4());
    callTest400();
    }
    
    
  2. 子类必须调用父类的构造器,完成父类的初始化,他其实有个super 的一个动作super();默认调用父类的无参构造器。

    
    //子类
    public class Graduate extends Student {
        public Graduate() {
        //super();默认调用父类的无参构造器
            System.out.println("子类构造器被调用");
        }
    }
    
    //父类
    public class Student {
    //共有属性
    
        public Student() {
            System.out.println("父类构造器被调用");
        }
    }
    public class extends01 {
        public static void main(String[] args) {
        }
    }

  3. 当创建子类对象的时候,不管使用子类的哪个构造器,默认情况下总会调用父类的无参构造器,如果父类没有提供,则必须在子类中用super去指定使用哪个父类的构造器完成初始化否则不通过。

    //父类
    //    public Student() {
    //        System.out.println("父类构造器被调用");
    //    }
    
    
        public Student(String name) {
            System.out.println("public Student(String name)构造器被调用");
        }
    //默认构造器没了。做一个有参的,默认的被覆盖了
    
    //就要用super
    //子类
    package com.jicheng;
    
    public class Graduate extends Student {
        public Graduate() {
            super("jack");
            System.out.println("子类构造器被调用");
        }
    
        public void testing(){
            System.out.println("大学生"  + name + "正在考小写数学");
        }
    }
    

  4. 如果希望调用某个父类构造器,则显示的调用以下super(参数列表)。

  5. super使用时,需要放在构造器第一行

  6. super和this都只能在构造器第一行使用,因此两个方法不能在同一个构造器

  7. Object是所有类的基类(ctrl + H可以看类的继承关系)

  8. 父类构造器的调用不限于直接父类,将会一直追溯到Object类(顶级父类)

  9. 子类最多继承一个父类,java 是单继承机制

  10. 如何让A类继承B类和C类呢,通俗来说就是你不可以当我爸爸,但是你能当我爷爷。A继承B,B继承C。也就相当高于A继承了C

 本质分析(重要)

 

 

加载类信息,从最父类开始加载,在堆中先给爷爷分配空间,再给爸爸开空间最后给儿子。

找属性的话,从底部(最子类)向上找(近的),如果允许访问,直接输出,如果private就不能访问。就报错 。如果比如说爸爸类有age但是私有,爷爷也有,还是找不到,因为在爸爸这里已经找到了但是没权限报错。

练习1

this指的是调用本类的构造器带有abc这个参数的构造器也就是下边那个

有个默认super    所以答案为a,b_name,b 

我是A类,B类 有参,C类有参,C类无参

练习2 

//Computer父类
package test3;

public class Test3 {
    public static void main(String[] args) {
        PC pc = new PC("intex",16,500,"IBM");
        pc.printInfo();
    }

}
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 getDetails(){
        return "cpu=" + cpu + "memory=" + memory + "disk= " + disk;
    }
//get set方法
    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;
    }
}
//PC子类
package test3;

public class PC extends Computer{
    private String brand;

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    //Idea根据继承规则自动把构造器调用写好,父类的熟属性由父类初始化,子类的属性由子类的构造器初始化(继承的基本思想)
    public PC(String cpu, int memory, int disk, String brand) {
        super(cpu, memory, disk);
        this.brand = brand;

    }
    //返回PC信息,调用父类的getdetails方法得到相关属性
    public void printInfo(){
        System.out.println("PC信息如下");
        System.out.println(getDetails() + "brand =" + brand);

    }

}

4.3 super关键字

super:代表父类的引用,用于访问父类的属性方法和构造器

 基本语法

  1. 访问父类的属性,但是不能访问父类private的属性。如下只能访问n1,n2,n3,语法是super.属性
    //父类
    package super1;
    
    public class A {
      public int n1 = 100;
      protected int n2 = 200;
      int n3 = 300;
      private int n4 = 400;
    }
    //子类
    package super1;
    
    public class B  extends A{
        public void hi(){
            System.out.println(super.n1 +super.n2 + super.n3);
        }
    }
    
    
  2.  可以访问父类的方法,但是不能访问父类的私有方法,语法是super.方法(参数列表),例子和上面属性一样
  3. 访问父类的构造器,super只能放在构造器的第一句,且只能一句super,默认是调无参的,想调哪个就写参数。

细节 

  1. 调用父类构造器的好处(分工明确,父类属性由父类初始化,子类属性由子类初始化)上述例子有说过,子类用的时候只不过调用一下
  2.  当子类中有父类中的成员(属性和方法)重名的时候,为了访问父类成员,必须用super区分。如果没有重名,super,this,直接访问的效果一样的(重要)找方法时候,先找本类如果有可以调用直接调用,如果没有再找父类。父类没有就继续找父类的父类,知道Object类。如果找到了但是不能访问(私有),报错cannot access。如果没有找到,会报错不存在。this.cal和cal寻找的逻辑一样,super.cal逻辑是直接找父类。属性和方法寻找顺序和方法一样,具体看示例图。
  3. super的访问不限于父类,如果有爷爷类有同名方法,也可以用super去访问爷爷类成员。如果基类都有同名的成员,使用super访问遵循就近原则A -> B -> C

4.4 方法重写/覆盖(override) 

介绍:

方法覆盖:子类有一个方法和父类的某个方法的名称、返回类型和参数完全一样,就是子类的方法覆盖了父类的方法。 

细节:

  1. 子类和父类方法的名称和参数列表相同
  2. 子类方法的返回类型和父类方法的返回类型要一样,或者是父类的返回类型是子类
  3. 子类方法不能缩小父类方法的访问权限  public > protected > 默认 > private

练习一: 方法重载和重写的区别

 练习二

//主类
package override1;

public class override_1
{
    public static void main(String[] args) {
        Person jack = new Person("jack", 11);
        System.out.println(jack.say());

        Student tom = new Student("Tom", 12, 88918876, 87.5);
        System.out.println(tom.say());
    }
}
//Person类
package override1;

public class Person {
    private String name;
    private int age;


    public String say(){
        return "name = " + name + "age = " + 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;
    }
}
//Student类
package override1;

public class Student extends Person{
    private int id;
    private double score;

    public String say(){
        return super.say() + "id = "  + id +  "score = " + score;//用super调用父类的再加上子类的即可
    }

    public Student(String name, int age, int id, double score) {
        super(name, age);
        this.id = id;
        this.score = score;
    }
}

4.5 多态

简单介绍

多态:方法和对象具有多种形态。建立在封装和继承上。 

  1. 方法的多态,重写和重载就体现多态  。
    package Poly;
    
    import static java.lang.Long.sum;
    
    public class polyMethod {
        public static void main(String[] args) {
            //方法重载体现多态,通过不同的参数去调用sum方法,就会调用不同的方法
            //因此对sum来说,就是多态的体现
            A a = new A();
            System.out.println(a.sum(5,10));
            System.out.println(a.sum(5,10,20));
           //方法的重写体现多态,根据对象不一样,会调用不同的方法
            B b = new B();
            a.say();
            b.say();
        }
    }
    
    class B {
        public void say(){
            System.out.println("B方法被调用");
        }
    }
    class A extends  B{
        public int sum(int n1 , int n2){
            return  n1 + n2;
        }
        public int sum(int n1, int n2, int n3){
            return n1 + n2 + n3;
        }
        public  void say(){
            System.out.println("A方法被调用");
        }
    }
  2. 对象的多态(核心+重点)(1)一个对象的编译类型和运行类型可以不一致,可以父类的引用指向子类的对象,下面编译类型Animal,运行类型是Dog(2) 编译类型在定义对象时候就确定了不能改变(3)运行类型是可以改变的(4)编译类型看定义时等号的左边,运行类型看等号的右边

 例子:对象的多态

 如果不使用多态,会发现随着食物和动物种类的增多,代码会变得越来越冗余,很难管理维护,Master类中会出现大量的方法重载 

//Master类

package Poly_01;

public class Master {
    private String name;

    public Master(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    //构成方法的重载
    //完成主人给小狗喂骨头
    public void feed(Dog dog,Bone bone){
        System.out.println("主人" + name + "给" + dog.getName() + "吃" + bone.getName());
    }
    //主人给小猫喂鱼
    public void feed(Cat cat,Fish fish){
        System.out.println("主人" + name + "给" + cat.getName() + "吃" + fish.getName());
    }
}

解决:利用对象的多态,比如再加一个对象在food或者animal的子类一样直接这么管理就行


    //使用多态机制可以统一管理主人喂食的问题
    //animal的编译类型是Aniamal,可以接收Animal子类的对象
    //food编译类型是Food,可以指向Food的子类的对象
    public void feed(Animal animal,Food food){
        System.out.println("主人" + name + "给" + animal.getName() + "吃" + food.getName());
    }
}

细节

  1. 多态的前提是:两个对象的类存在继承关系
  2. 多态的向上转型本质:是父类的引用指向了子类的对象/语法:父类中所有满足权限的成员,不能调用子类的特有成员(比如猫的卓老鼠方法)(因为在编译阶段,能调用哪些成员,由编译类型决定)最终的运行效果要看子类的具体实现 !!!即调用方法时,从子类开始查找方法 然后调用,规则和方法调用规则一致。
  3. 思考:不能调用特有成员,那我要是想调特有的呢?多态的向下转型 语法:子类类型 引用名 = (子类类型)父类引用。只能强转父类的引用不能强转父类的对象。 (2) 如果你要强转要求i你这个父类引用原先就是指向你这个子类类型。以前比如Animal  animal= new Cat();你现在就不能  Dog dog = (Dog) animal;  (3)当向下转型后,就可以调用子类类型的所有成员了。
Cat cat = (Cat) animal;//向下转型

注意事项

  1. 属性没有重写之说!!!属性的值看编译类型。
  2. instanceOf,判断对象的运行类型(左边)是否为某某类型或者其子类型。

练习一 

属性找编译类型,调用方法找运行类型,运行类型没找到的去父类找。答案:20,20,true,10,20

4.6 java动态绑定机制(重要)(属性看编译类型,方法看运行类型)

介绍

  1. 当调用对象方法的时候,该方法和该对象的内存地址/运行类型绑定
  2. 当调用对象属性的时候,没有动态绑定机制,哪里声明哪里使用

4.7 多态的应用

1.多态数组 

 数组的定义类型为父类类型,里面保存的实际元素类型为子类类型。

可以看到persons【i】编译类型一致是person,运行类型根据实际情况判断,这样的话say方法非常灵活。 

//POLY主类
package duotaishuzu;

public class PolyArray {
    public static void main(String[] args) {
        //因为都要放在一个数组里面,所以用父类创建数组
        Person[] persons = new Person[5];
        persons[0] = new Person(20,"jack");
        persons[1] = new Student("Tom",20,85.2);
        persons[2] = new Student("Jerry",15,87.6);
        persons[3] = new Teacher("Tonny",28,3000);
        persons[4] = new Teacher("Pig",60,15000);
//编译类型事Person
        for(int i = 0; i < persons.length; i++){
            System.out.println(persons[i].say());
            //做一个判断,做向下类型转换。判断persons【i】的运行类型是不是student
            if(persons[i] instanceof Student){
                Student student = (Student) persons [i];
                student.study();
//(Student) persons [i].study();
            }
            if(persons[i] instanceof Teacher){
                Teacher teacher = (Teacher) persons[i];
                teacher.teach();
            }
        }
    }
}

从上面的代码可以看出。要调用特有的方法不能用persons【i】.teach和study直接调用。 用instanceof判断运行类型

Person父类
package duotaishuzu;

public class Person {
    private int age;
    private String name;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String say(){
      return "name " + name +"\t" + "age" + age;
    }
}
//student和teacher子类
package duotaishuzu;

public class Student extends Person{
    private double score;
    public Student(String name,int age, double score){
        super(age,name);
        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);
    }

    public void study(){
        System.out.println("学生" +getName() + "正在授课");
    }
}


package duotaishuzu;

public class Teacher extends Person{
    private double salary;

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public Teacher(String name, int age, double salary) {
        super(age, name);
        this.salary = salary;
    }
        @Override
        public String say(){
        return super.say() + salary;
        }


        public void teach(){
            System.out.println("老师:" + getName() + "正在授课");
        }

}

2.多态参数

方法定义的形参类型为父类类型,实参类型允许为子类类型 

这道题目的两个难点是一个是动态绑定机制,另一个是多态的下转型。 

package polypara;

import sun.plugin2.applet.ManagerCache;

public class poplpara {
    public static void main(String[] args) {
        Common tom = new Common("tom", 2000);
        manager lilan = new manager("lilan", 5000,20000);
        poplpara poplpara = new poplpara();
        poplpara.showEmpAnnual(tom);
        poplpara.showEmpAnnual(lilan);
        poplpara.testwork(tom);
        poplpara.testwork(lilan);
    }

    public void showEmpAnnual(Employee e){
        System.out.println(e.getAnnual());//动态绑定机制
    }

    public void testwork(Employee e){
        if(e instanceof Common){
            ((Common) e).work();//多态的下转型
        }
        else if(e instanceof manager){
            ((manager) e).manage();
        }
    }
}


class Employee{
    public String name;
    private double salary;

    public Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    //计算年工资的方法
    public double getAnnual(){
        System.out.println("年工资是:");
        return salary * 12;
    }
}

class Common extends Employee{
    public Common(String name, double salary) {
        super(name, salary);
    }
    //工作方法
    public void work(){
        System.out.println("员工" + getName() + "正在工作");
    }

    @Override
    public double getAnnual() {
        return super.getAnnual();
    }
}

class manager extends Employee{
    private  double bonus;

    public manager(String name, double salary, double bonus) {
        super(name, salary);
        this.bonus = bonus;
    }
    //管理方法
    public void manage(){
        System.out.println("经理" + getName() + "正在管理");
    }

    @Override
    public double getAnnual() {
        return super.getAnnual() + this.bonus;
    }
}

 5.Ocject类

object类是类层次结构的根类,所有的类都能用object类的方法

5.1 ==和eqals的区别

(1)==方法

package object;

import jdk.nashorn.internal.ir.BaseNode;

public class demo {
    public static void main(String[] args) {
        A a =new A();
        A b = a;
        A c = a;
        System.out.println(a == c);
        System.out.println(b == c);
        B obj = a;
        System.out.println(obj == c);//只要满足两个对象的地址是一样的,那就是true
    }
}
//这三个都是true
class A extends B {}

class B {}

 (2)equals 方法(想找源码的话ctrl+b)

是Object类中的方法,只能判断引用类型,默认判断是否地址相等,子类中往往重写(比如String,integer(这个是int的包装类))

        Integer integer = new Integer(1000);
        Integer integer1 = new Integer(1000);
        System.out.println(integer1 == integer);//false,因为不是同一个对象
        System.out.println(integer1.equals(integer));//true。因为已经重写了
        //String也是同理

(3)练习1 重写equals方法

package object;

public class duotaichongxie {
    public static void main(String[] args) {
        Person person1 = new Person("pig",'男',15);
        Person person2 = new Person("pig",'男',15);
        System.out.println(person2.equals(person1));
    }

}
class Person{
    private String name;
    private int age;
    private char gender;


    //重写一下equals
    public boolean equals(Object obj){
        if(obj instanceof Person){
            Person p = (Person) obj;//向下转型,因为我要得到obj的各个属性
            return this.name.equals(p.name) && this.age == p.age && this.gender == p.gender;
        }
        else{
            return false;
        }
    }
    public Person(String name, char gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }

}

练习2

答案:FTFTF

练习3

第一个类型自动转换T,T,T,F,T,F(编译报错)

5.2 hashcode方法

  1. 提高具有哈希结构容器的效率
  2. 两个引用,如果指向的是同一个对象,则哈希值一定是一样的
  3. 两个引用,如果指向的是不同对象,则哈希值不一样
  4. 哈希值主要根据地址来计算但是不能完全等价于地址
  5. 我感觉可以理解为内部地址转换为整数,也就是地址的映射
package object;
public class hashcode {
    public static  void main(String[] args) {
        AA aa = new AA();
        AA aa1 = new AA();
        AA b = aa;
        System.out.println(aa.hashCode());//460141958
        System.out.println(aa1.hashCode());//1163157884
        System.out.println(b.hashCode());//460141958
    }
}
class AA{}

 5.3 toString方法

1.返回该对象的字符串表示,默认返回的是全类名(包名+ 类名)+  @  +哈希值的十六进制,子类往往重写这个方法,用来返回对象的属性信息

package object;
public class Tostring {
    public static void main(String[] args) {
        Monster monster = new Monster("小妖怪", "巡山", 5000);
        System.out.println(monster.toString() + "hashcode=" + monster.hashCode());

    }
}
//Object的Tostring源码
//(1)getClass().getName()类的全类名(类名+包名)
//(2)Integer.toHexString(hashCode()),将对象的哈希值转为16进制
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;
    }

}

2.重写tostring方法,在打印对象和拼接对象时候输出对象的属性

 @Override
    public String toString() {//重写后一般是把对象的属性输出出来
        return "Monster{" +
                "name='" + name + '\'' +
                ", job='" + job + '\'' +
                ", sal=" + sal +
                '}';
    }

3.当输出一个对象的时候,toString方法会被默认调用,也就是Syste.out.println(monster);就会默认调用monster,toString()

 5.4 finalize方法

  1. 当对象被回收的时候,系统用该对象的finalize 方法,子类可重写该方法,做一些资源的释放。
  2. 当某个对象没有任何引用的时候,则jvm‘认为这个对象是个垃圾,会销毁,销毁前会调用finalize
  3. 垃圾回收机制有自己的GC算法,由系统来决定。垃圾回收机制的主动调用可以通过System.gc()主动触发

 

package object;
public class finalize {
    public static void main(String[] args) {
        Car ab = new Car("宝马");
        ab = null;//这时这个对象就是一个垃圾,垃圾回收器就会销毁,也就是把堆内部分配的空间回收在销毁前会调用该对象的finalize方法
        //程序猿就可以写自己的业务逻辑(比如释放资:比如数据库连接,或者打开的文件)
        //如果不重写finalize方法,就会调用object类的finalize默认处理
        System.gc();//主动调用垃圾回收期
        System.out.println("程序结束了");
    }
}
//结果程序结束了
//我们销毁 汽车宝马
//我们释放了资源。。。
class  Car{
    String name;

    public Car(String name) {
        this.name = name;
    }

    @Override
    protected void finalize() throws Throwable {
        System.out.println("我们销毁 汽车" + name);
        System.out.println("我们释放了资源。。。");
    }
}


6.断点调试(debug)

在断点调试过程中,是处于一个运行状态,是以对象的运行类型来执行的

6.1快捷键

F7(跳入):跳入方法内

F8(跳过):逐行执行代码

SHIFT+F8:跳出方法

F9(resume):执行到下一个断点

 6.2 断点demo1(数组越界)

 6.3 断点demo2(追踪源代码) 

F7一直往里追可以追到头快排,补:可以动态的加断点

 6.4 断点练习  

  • 42
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A_SHOWY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值