深入类和对象

深入类和对象

大家好呀!我是小笙!前几天被培训班的老师考察基础,发现漏洞还是有很多的,我想进一步学习java基础,所以我跟着韩老师学Java,以下是我的笔记

IDEA开发工具的简单分布介绍

深入类和对象

本质就是文件夹 类的本质就是文件 package关键字

作用: 1.区分相同名字的类 2.可以很好的管理类 3.控制方法范围通过访问修饰符

包的规则和规范

包的命名规则:只能包含数组,字母,下划线,小圆点,但不能用数组开头,不能是关键字或者保留字

包的命名规范:全名都是小写字母 + 小圆点

比如 : com.公司名.项目名.业务模块名

常用包

*指的是包下所有的类都导入

深入类和对象

细节注意

  • package的作用是声明当前类所在的包,需要放在类的最上面(意思就是package上面除了注释什么都不能放) ,一个类最多只有一句package

  • import关键字放在package下面,在类定义前面,可以有多句,没有顺序要求

    // 一个类中最多只有一个package
    package com.al_tair.study;
    
    // import关键字放在package下面,在类定义前面,可以有多句,没有顺序要求
    import java.util.Scanner;
    import java.util.Arrays;
    
    // 类定义
    public class study{
        public static void main(String[]args){}
    }
    

访问修饰符

访问修饰符的种类

  • public : 对全部包中的类开放
  • protected : 对不同包的子类和同一个包中的类公开
  • 默认访问修饰符(无修饰符):对同一个包中的类(包含子类)公开,但是对不同包的子类不公开
  • private : 只有类本身可以访问

深入类和对象

使用注意细节

  • 修饰符可以用来修饰类中的属性,成员方法以及类
  • 只能用默认的和public来修饰类

面向对象编程的三大特征

封装, 继承,多态

封装

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

好处: 1.隐藏实现的细节 2.可以对数据进行验证,保证数据安全合理

封装的实现步骤

深入类和对象

继承

extends 关键字

格式:class 子类 extends 父类 { }

好处:解决代码复用性,当多个类中有相同的属性和方法时候,我们可以抽出相同属性和方法作为父类

深入类和对象

注意细节

  • 子类继承了父类所有的属性和方法,但是私有属性和方法不能被直接访问,子类和父类之间必须满足 is - a 的逻辑关系

  • 子类必须调用父类的构造器,完成父类的初始化,默认无参父类构造器,当父类没有无参构造器并且子类未用super指明对应的父类的构造器,编译不会通过

    // 父类
    public class person {
        public person() {
            System.out.println("父类构造器");
        }
    }
    
    // 子类
    public class Child extends person{
        public Child() {
            // 默认 super();
            System.out.println("子类构造器");
        }
    }
    
    class test{
        public static void main(String[] args) {
            Child child = new Child();
        }
    }
    
    // 运行结果
    父类构造器
    子类构造器
    
  • super and this 关键字使用的时候必须放在构造器的第一行,因此这两个方法调用不能共存在一个构造器

  • java所有类都是Object类的子类

  • 父类的构造器的调用不仅限于直接父类,会一直追朔直到Object类(*父类)

  • 子类最多只能继承一个父类(单继承机制)

内存分布图

查找属性和方法数据根据就近原则

深入类和对象

详解super关键字

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

注意细节:

  • 无法访问父类的私有方法和属性
  • 使用的时候必须放在构造器的第一行,因此只能调用一次父类的构造器
  • 当子类的属性,方法和父类重名时,为了访问父类的成员,必须通过super关键字来完成

this 和 super 的区别

深入类和对象

多态

概念:方法或者对象具有多种状态,多态是建立在封装和继承之上的

方法的重载和重写体现了方法的多态

对象的多态具体体现

  • 前提条件:两个对象(类)存在继承关系

  • 一个对象的编译类型和运行类型可以不一致

    // Animal 父类 Dog 子类 Cat 子类
    Animal  animal = new Dog(); // 编译类型 Aniaml 运行类型 Dog
    animal = new Cat(); // 运行类型是可以改变的
    
  • 编译类型在定义对象时候就确定了

  • 运行类型是可以改变的

  • 编译类型看定义,运行类型看 new 对象

细节分析

  • 多态的向上转型

    1. 本质:父类的引用指向子类的对象
    2. 语法:父类类型 引用名 = new 子类类型();
    3. 特点:编译类型看定义,运行类型看 new 对象
    4. 用该对象调用方法的时候,只能调用父类中的方法,不能调用子类特有的方法,因为编译不通过;但是调用方法在运行类型中是先从子类开始查找方法
    5. 属性没有重写的说法,所以属性的值看编译类型
  • 多态的向下转型

    1. 语法:子类类型 引用名 = (子类类型)父类引用;

    2. 只能强转父类的引用,不能强转父类的对象

    3. 可以调用子类类型中的所有成员

    4. 我的理解:就是让编译和运行类型上进行一个统一

      // 举例
      Animal  animal = new Dog(); // 编译类型 Aniaml 运行类型 Dog
      Dog dog = (Dog) animal; // // 编译类型 Dog 运行类型 Dog 
      
动态绑定机制

具体体现:

  • 当调用对象方法时候,该方法会和该对象的内存地址/ 运行类型进行动态绑定
  • 当调用对象的属性的时候没有动态绑定的说法

举例说明:

// 举例
public class demo{
    public static void main(String[] args){
        father f = new son();
        System.out.println(f.sum()); // 40
        System.out.println(f.sum2());  // 60
    }
}

class father{ // 父类
    public int attribute = 10;
    public int sum(){
        return getAttribute() + 10; // getAttribute()绑定的是子类的该方法
    }
    public int sum2(){
        return attribute + 50; // 属性没有动态绑定机制
    }
    public int getAttribute(){
        return attribute;
    } 
    
}

class son extends father{ // 子类
    public int attribute = 30;
    public int getAttribute(){
        return attribute;
    }
}

Object类详解

深入类和对象

equals

equals方法 和 == 比较运算符 的区别

== :如果判断基本数据类型,判断值是否相同;如果判断引用数据类型,判断的是地址是否相同(是否是 同一个对象)

equals:是Object类中的方法,只能用来判断引用类型,默认是判断地址是否相同,但是像String类重写了该方法,用来判断字符串值是否相同

// Object类的源码
public boolean equals(Object obj) {
    return (this == obj);
}

// String类的源码
   /**
     * Compares this string to the specified object.  The result is {@code
     * true} if and only if the argument is not {@code null} and is a {@code
     * String} object that represents the same sequence of characters as this
     * object.
     */
    public boolean equals(Object anObject) {
        if (this == anObject) { // 比较地址是否相同
            return true;
        }
        if (anObject instanceof String) { // 判断是否为String 或者 String的父类
            String aString = (String)anObject; // 向下转型:目的是为了获得String类的属性和方法
            if (!COMPACT_STRINGS || this.coder == aString.coder) {
                return StringLatin1.equals(value, aString.value);
            }
        }
        return false;
    }

// StringLatin1类的源码 底层就是比较字符数组中每个字符是否相同
 @HotSpotIntrinsicCandidate
    public static boolean equals(byte[] value, byte[] other) {
        if (value.length == other.length) {
            for (int i = 0; i < value.length; i++) {
                if (value[i] != other[i]) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }
hashCode

作用:返回该对象的哈希码值,是为了提高哈希表的性能

注意细节

  • 提高具有哈希结构的容器的效率
  • 两个引用都指向同一个对象,则哈希值一定相同
  • 哈希值主要是根据地址来的,将对象的内部地址转换成一个整数来实现的
toString

默认返回:全类名 + @ + 哈希值十六进制

作用:用于返回该对象的属性信息

// Object源码
// java.lang.Object@16b98e56
public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

注意细节

  • 当直接输出一个对象时,toString方法会被默认的调用

    Object o = new Object();
    System.out.println(o.toString()); // java.lang.Object@16b98e56
    System.out.println(o); //java.lang.Object@16b98e56
    
finalize

概念:当垃圾回收器确定不存在该对象的更多引用时,由对象的垃圾回收器调用此方法

注意细节

  • 当某个对象没有任何引用时,则jvm虚拟机就会来销毁该对象,在销毁该对象前,就会调用该对象的finalize方法

    public class person {
    	public person() {}
    
        // 该方法已经被废除,不推荐使用
        @Override
        protected void finalize() throws Throwable {
            System.out.println("我已经被销毁了...");
        }
    }
    
    class test{
        public static void main(String[] args) {
            new person();
            System.gc(); // 运行垃圾回收器
        }
    }
    
    // 显示效果:我已经被销毁了...
    
  • 垃圾回收机制的调用,由系统来决定,我们可以通过System.gc() 主动触发垃圾回收机制

断点调试

断点调试(idea)默认快捷键
  • F7:跳入方法
  • F8:逐行执行代码
  • shift+F8:跳出方法
  • F9:执行到下一个断点
Idea debug如何进入 Jdk源码
解决方法1

使用force step into : 快捷键 alt + shift + F7

解决方法2

这个配置一下就好了:
点击Setting --> Build,Execution,Deployment --> Debugger --> Stepping
把Do not step into the classes中的java.*,javax.*取消勾选

深入类和对象

相关面试题

1.请说明一下final, finally, finalize的区别

final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。
finally是异常处理语句结构的一部分,表示总是执行。
finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源
回收,例如关闭文件等。

2.请说明面向对象的特征有哪些方面

  1. 抽象:抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面。抽象并不打算了解全部问题,而只
    是选择其中的一部分,暂时不用部分细节。抽象包括两个方面,一是过程抽象,二是数据抽象。
  2. 继承:继承是一种联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法。对象的一个新类可以从现有的类中派
    生,这个过程称为类继承。新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类)。派生
    类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。
  3. 封装:封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即现实世界可以被描绘成一
    系列完全自治、封装的对象,这些对象通过一个受保护的接口访问其他对象。
  4. 多态性:多态性是指允许不同类的对象对同一消息作出响应。多态性包括参数化多态性和包含多态性。多态性语言具有灵活、抽象、行为共享
    、代码共享的优势,很好的解决了应用程序函数同名问题。

3.请说明Java是否支持多继承

Java中类不支持多继承,只支持单继承(即一个类只有一个父类)。 但是java中的接口支持多继承,,即一个子接口可以有多个父接口。(接口的作用是用来扩展对象的功能,一个子接口继承多个父接口,说明子接口扩展了多个功能,当类实现接口时,类就扩展了相应的功能)

上一篇:后续Java常用类


下一篇:线性分类器