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

embedded/2024/10/22 14:29:10/

🔥博客主页: 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 例子:

java">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 如何导入包

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

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

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

java">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 

java">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方法进行判断。可以有效的限制数据。

java">
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 父类{},子类会自动拥有父类定义的属性和方法

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

 

java">//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. 子类继承了父类的所有方法和属性,但是私有属性不能在子类中直接访问,要通过父类提供的公共的方法去访问 例如
    java">//对于私有属性和私有方法
    //在父类中
    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();默认调用父类的无参构造器。

    java">
    //子类
    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去指定使用哪个父类的构造器完成初始化否则不通过。

    java">//父类
    //    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 

java">//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;}
}
java">//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.属性
    java">//父类
    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

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

 练习二

javascript">//主类
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());}
}
java">//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;}
}
java">//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. 方法的多态,重写和重载就体现多态  。
    java">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类中会出现大量的方法重载 

java">//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的子类一样直接这么管理就行

java">//使用多态机制可以统一管理主人喂食的问题//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)当向下转型后,就可以调用子类类型的所有成员了。
java">Cat cat = (Cat) animal;//向下转型

注意事项

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

练习一 

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

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

介绍

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

4.7 多态的应用

1.多态数组 

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

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

java">//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);
//编译类型事Personfor(int i = 0; i < persons.length; i++){System.out.println(persons[i].say());//做一个判断,做向下类型转换。判断persons【i】的运行类型是不是studentif(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判断运行类型

java">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;}
}
java">//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方法@Overridepublic 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;}@Overridepublic String say(){return super.say() + salary;}public void teach(){System.out.println("老师:" + getName() + "正在授课");}}

2.多态参数

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

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

java">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() + "正在工作");}@Overridepublic 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() + "正在管理");}@Overridepublic double getAnnual() {return super.getAnnual() + this.bonus;}
}

 5.Ocject类

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

5.1 ==和eqals的区别

(1)==方法

java">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的包装类))

java">        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方法

java">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;//重写一下equalspublic 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. 我感觉可以理解为内部地址转换为整数,也就是地址的映射
java">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());//460141958System.out.println(aa1.hashCode());//1163157884System.out.println(b.hashCode());//460141958}
}
class AA{}

 5.3 toString方法

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

java">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方法,在打印对象和拼接对象时候输出对象的属性

java"> @Overridepublic 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()主动触发

 

java">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;}@Overrideprotected 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 断点练习  


http://www.ppmy.cn/embedded/87418.html

相关文章

【解决方案】华普微汽车智能钥匙解决方案

一、方案概述 1.什么是被动式无钥匙进入 "被动式无钥匙进入"&#xff08;Passive Keyless Entry&#xff09;是一种用于车辆、建筑物或其他设施的访问控制系统。它利用无线射频技术自动判断用户是否接近&#xff0c;并进行身份识别以执行开锁或落锁动作&#xff0c…

学习008-02-04-08 Localize UI Elements(本地化UI元素)

Localize UI Elements&#xff08;本地化UI元素&#xff09; This lesson explains how to localize an XAF application. It describes how to translate UI elements into German and create a multi-language application. 本课介绍如何本地化XAF应用程序。它描述了如何将U…

Redis 序列化 GenericJackson2JsonRedisSerializer和Jackson2JsonRedisSerializer的区别

GenericJackson2JsonRedisSerializer 和 Jackson2JsonRedisSerializer 是 Spring Data Redis 提供的两种基于 Jackson 的 Redis 序列化器。 它们的主要区别在于序列化和反序列化的方式以及适用的场景。 GenericJackson2JsonRedisSerializer 序列化方式&#xff1a;在序列化对…

运维-6-采用LPG搭建轻量级日志收集系统

参考Grafana 安装配置教程 1 Grafana Grafana是一个通用的可视化工具。对于Grafana而言&#xff0c;Prometheus这类为其提供数据的对象均称为数据源&#xff08;Data Source&#xff09;。目前&#xff0c;Grafana官方提供了对&#xff1a;Graphite, InfluxDB, OpenTSDB, tde…

构建稳固与安全的网络环境:从微软蓝屏事件中的教训学习

近日&#xff0c;一场由微软视窗系统软件更新引发的全球性“微软蓝屏”事件震惊了整个科技界。这次事件不仅暴露了现代IT基础设施在面对大规模软件缺陷时的脆弱性&#xff0c;也引发了对网络安全与系统稳定性的深刻思考。在本文中&#xff0c;我们将探讨这次事件的根源、影响以…

达梦数据库系列—32.多版本并发控制MVCC

在多版本控制以前&#xff0c;数据库仅通过锁机制来实现并发控制。数据库对读操作上共享锁&#xff0c;写操作上排他锁&#xff0c;这种锁机制虽然解决了并发问题&#xff0c;但影响了并发性。 DM 数据库基于物理记录和回滚记录实现行级多版本支持&#xff0c;数据页中只保留物…

ChatGPT:宽列数据库是什么?

ChatGPT&#xff1a;宽列数据库是什么&#xff1f; 宽列数据库&#xff08;Wide-Column Store&#xff09;是一种 NoSQL 数据库&#xff0c;它的设计灵感来自于 Google 的 Bigtable。宽列数据库适用于处理大规模的分布式数据存储&#xff0c;特别是在需要高性能读写、灵活的数据…

服务器是否需要安装杀毒软件

现在许多服务器都自带杀毒软件&#xff0c;这些软件可以更好的保护服务器的安全&#xff0c;防止使用者的信息被泄露。那么服务器是否需要杀毒软件&#xff0c;这里壹基比小鑫就和大家一起看看。 一、为什么要装服务器杀毒软件&#xff1f; 装服务器杀毒软件主要是保护服务器安…