🔥博客主页: A_SHOWY
🎥系列专栏:力扣刷题总结录 数据结构 云计算 数字图像处理 力扣每日一题_
1.关于IDEA
1.1 IDEA目录
Idea的项目编译后,其class文件会存在out文件重,src存放源文件。
1.2 快捷键
- 删除当前行:CTRL + Y
- 复制当前行: CTRL + D
- 添加注释:CTRL + /
- 自动导入需要的类:ALT + ENTER
- 快速格式化:CRTL + Alt + L(可能会锁住QQ)
- 快速运行: Alt + Shift + F10
- 创建构造器:Alt + insert
- 查看一个类的层级关系:CTRL + H
- 光标放在方法上,CTRL + B,可以定位到哪个类的方法
- 自动分配变量名,在后边加.var
1.3 模板/自定义模板
- main:直接输出 public static void main(String[] args)
- sout:输出模板
- fori:循环模板
2.包
2.1 作用
- 区分相同名字的类
- 类很多的时候,可以很好的管理类
- 控制访问范围
2.2 基本语法
package(关键字,表示打包) com.hspedu(表示包名)
2.3 包的本质分析
包的本质是创建不同文件夹保存类文件
2.4 例子:![](https://img-blog.csdnimg.cn/direct/2e32daa45f6e46a08c722677e18bf075.png)
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.访问修饰符
四种访问控制修饰符,用来控制方法和属性的访问权限(范围)
- 公开级别:public修饰,对外公开
- 受保护基本:protected,对子类和同一个包中的类公开
- 默认级别:没有修饰符号,向同一个包的类公开
- 私有级别:private,只有类本身可以访问
3.1 注意事项
- 修饰符可以修饰类中的属性、成员方法和类
- 只有默认和public才能修饰类,遵循上述表
4.面向对象编程的三大特征
封装继承和多态(重点 + 难度)
4.1 封装(encapsulation)
把抽象出的数据(属性)和对数据的操作(方法)封装在一起,数据被保护在内部,程序其他部分只有通过被授权的操作【方法】才能对数据进行操作。
好处
-
隐藏实现的细节 方法<--调用
-
可以对数据进行验证,保证安全和合理性
步骤
- 对属性进行私有化
- 提供一个公共的方法(public)set方法,用于对属性的判断并且赋值,public void setXXX(类型参数名),可以加入数据验证的业务逻辑
- 提供一个公共的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);
}
}
细节
- 子类继承了父类的所有方法和属性,但是私有属性不能在子类中直接访问,要通过父类提供的公共的方法去访问 例如
//对于私有属性和私有方法 //在父类中 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(); }
-
子类必须调用父类的构造器,完成父类的初始化,他其实有个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) { } }
-
当创建子类对象的时候,不管使用子类的哪个构造器,默认情况下总会调用父类的无参构造器,如果父类没有提供,则必须在子类中用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 + "正在考小写数学"); } }
-
如果希望调用某个父类构造器,则显示的调用以下super(参数列表)。
-
super使用时,需要放在构造器第一行
-
super和this都只能在构造器第一行使用,因此两个方法不能在同一个构造器
-
Object是所有类的基类(ctrl + H可以看类的继承关系)
-
父类构造器的调用不限于直接父类,将会一直追溯到Object类(顶级父类)
-
子类最多继承一个父类,java 是单继承机制
-
如何让A类继承B类和C类呢,通俗来说就是你不可以当我爸爸,但是你能当我爷爷。A继承B,B继承C。也就相当高于A继承了C
本质分析(重要)
加载类信息,从最父类开始加载,在堆中先给爷爷分配空间,再给爸爸开空间最后给儿子。
找属性的话,从底部(最子类)向上找(近的),如果允许访问,直接输出,如果private就不能访问。就报错 。如果比如说爸爸类有age但是私有,爷爷也有,还是找不到,因为在爸爸这里已经找到了但是没权限报错。
练习1![](https://img-blog.csdnimg.cn/direct/10c4610799ae4bc39b49c0b8d4a45636.png)
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:代表父类的引用,用于访问父类的属性方法和构造器
基本语法
- 访问父类的属性,但是不能访问父类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); } }
- 可以访问父类的方法,但是不能访问父类的私有方法,语法是super.方法(参数列表),例子和上面属性一样
- 访问父类的构造器,super只能放在构造器的第一句,且只能一句super,默认是调无参的,想调哪个就写参数。
细节
- 调用父类构造器的好处(分工明确,父类属性由父类初始化,子类属性由子类初始化)上述例子有说过,子类用的时候只不过调用一下
- 当子类中有父类中的成员(属性和方法)重名的时候,为了访问父类成员,必须用super区分。如果没有重名,super,this,直接访问的效果一样的(重要)找方法时候,先找本类如果有可以调用直接调用,如果没有再找父类。父类没有就继续找父类的父类,知道Object类。如果找到了但是不能访问(私有),报错cannot access。如果没有找到,会报错不存在。this.cal和cal寻找的逻辑一样,super.cal逻辑是直接找父类。属性和方法寻找顺序和方法一样,具体看示例图。
- super的访问不限于父类,如果有爷爷类有同名方法,也可以用super去访问爷爷类成员。如果基类都有同名的成员,使用super访问遵循就近原则A -> B -> C
4.4 方法重写/覆盖(override)
介绍:
方法覆盖:子类有一个方法和父类的某个方法的名称、返回类型和参数完全一样,就是子类的方法覆盖了父类的方法。
细节:
- 子类和父类方法的名称和参数列表相同
- 子类方法的返回类型和父类方法的返回类型要一样,或者是父类的返回类型是子类
- 子类方法不能缩小父类方法的访问权限 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 多态
简单介绍
多态:方法和对象具有多种形态。建立在封装和继承上。
- 方法的多态,重写和重载就体现多态 。
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方法被调用"); } }
- 对象的多态(核心+重点)(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());
}
}
细节
- 多态的前提是:两个对象的类存在继承关系
- 多态的向上转型本质:是父类的引用指向了子类的对象/语法:父类中所有满足权限的成员,不能调用子类的特有成员(比如猫的卓老鼠方法)(因为在编译阶段,能调用哪些成员,由编译类型决定)。最终的运行效果要看子类的具体实现 !!!即调用方法时,从子类开始查找方法 然后调用,规则和方法调用规则一致。
- 思考:不能调用特有成员,那我要是想调特有的呢?多态的向下转型 语法:子类类型 引用名 = (子类类型)父类引用。只能强转父类的引用不能强转父类的对象。 (2) 如果你要强转要求i你这个父类引用原先就是指向你这个子类类型。以前比如Animal animal= new Cat();你现在就不能 Dog dog = (Dog) animal; (3)当向下转型后,就可以调用子类类型的所有成员了。
Cat cat = (Cat) animal;//向下转型
注意事项
- 属性没有重写之说!!!属性的值看编译类型。
- instanceOf,判断对象的运行类型(左边)是否为某某类型或者其子类型。
练习一
属性找编译类型,调用方法找运行类型,运行类型没找到的去父类找。答案:20,20,true,10,20
4.6 java动态绑定机制(重要)(属性看编译类型,方法看运行类型)
介绍
- 当调用对象方法的时候,该方法和该对象的内存地址/运行类型绑定
- 当调用对象属性的时候,没有动态绑定机制,哪里声明哪里使用
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方法
- 提高具有哈希结构容器的效率
- 两个引用,如果指向的是同一个对象,则哈希值一定是一样的
- 两个引用,如果指向的是不同对象,则哈希值不一样
- 哈希值主要根据地址来计算但是不能完全等价于地址
- 我感觉可以理解为内部地址转换为整数,也就是地址的映射
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方法
- 当对象被回收的时候,系统用该对象的finalize 方法,子类可重写该方法,做一些资源的释放。
- 当某个对象没有任何引用的时候,则jvm‘认为这个对象是个垃圾,会销毁,销毁前会调用finalize
- 垃圾回收机制有自己的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一直往里追可以追到头快排,补:可以动态的加断点