韩顺平Java笔记(自用3)

  • 第8章  面向对象编程(中级部分)
  • 第10章  面向对象编程(高级部分)

目录

第8章 面向对象编程(中级部分)

8.1 面向对象编程三大特征

8.1.1 基本介绍

8.1.2 封装介绍

8.1.3 封装的理解和好处

8.1.4  封装的实现步骤 (三步)

 8.1.5  测试代码

8.2  面向对象编程-继承

8.2.1  为什么需要继承

 8.2.2  继承的基本语法

 8.2.3  继承给编程带来的便利

8.2.4  继承的深入讨论/细节问题

8.3  super 关键字

8.3.1  基本介绍

8.3.2  基本语法

8.3.3  super 给编程带来的便利/细节

 8.3.4  super 和 this 的比较

8.4  方法重写/覆盖(override)

8.4.1  基本介绍

 8.4.2  注意事项和使用细节

8.5  面向对象编程-多态

8.5.1  多[多种]态[状态]基本介绍

8.5.2  对象的多态 (核心,困难,重点)

 8.5.3  多态注意事项和细节讨论

8.6  Object 类详解

8.6.1  equals 方法

 8.6.2  如何重写 equals 方法

8.6.3  hashCode 方法

8.6.4  toString 方法

8.6.5  finalize 方法

第10章  面向对象编程(高级部分)

10.1  类变量内存布局

10.1.1  static关键字

 10.1.2  什么是类变量

 10.1.3  如何定义类变量

10.1.4  如何访问类变量

 10.1.5  类变量使用注意事项和细节讨论

 10.1.6  类方法基本介绍

 10.1.7  类方法的调用

 10.1.8  类方法使用注意事项和细节讨论

10.2 理解 main 方法语法 

10.2.1   深入理解 main 方法

10.3 代码块

10.3.2 基本语法

 10.3.3  代码块的好处

10.3.4  代码块使用注意事项和细节讨论

10.4  final 关键字

10.4.1 基本介绍

 10.4.2 final 使用注意事项和细节讨论

10.5  抽象类

10.5.1  抽象类的介绍

 10.5.2  抽象类使用的注意事项和细节讨论

10.5.3  解决之道-抽象类快速入门’​

10.6  接口

10.6.1  基本介绍

 10.6.2  案例

 10.6.3  注意事项和细节

10.6.4  实现接口 vs 继承类

10.7  常用类

10.7.1 内部类

10.7.2  成员内部类

10.7.3  静态内部类

 10.7.4  局部内部类

 10.7.5  匿名内部类

10.7.6  Object类

10.7.8  getClass()方法

10.7.9  hashCode()方法

10.7.10  toString()方法

10.7.11  equals()方法

10.7.12  finalize()方法


第8章 面向对象编程(中级部分)

8.1 面向对象编程三大特征

8.1.1 基本介绍

面向对象编程有三大特征:封装、继承和多态。

8.1.2 封装介绍

8.1.3 封装的理解和好处

8.1.4  封装的实现步骤 (三步)

 8.1.5  测试代码

public class test5 {
    public static void main(String[] args) {
        //调用无参构造,分别设置各个属性来获取值
        Account account1 = new Account();
        account1.setName("张三");
        account1.setAge(12);
        account1.setSex("男");
        System.out.println(account1.toString());
        System.out.println("====");
        //通过有参构造直接设置各个属性来获取值
        Account account2 = new Account("李四",25,"女");
        System.out.println(account2.toString());
    }
}

8.2  面向对象编程-继承

8.2.1  为什么需要继承

        继承可以解决代码复用,让我们的编程更加靠近人类思维.当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来声明继承父类即可。画出继承的示意图。

 8.2.2  继承的基本语法

 8.2.3  继承给编程带来的便利

        1) 代码的复用性提高了
        2) 代码的扩展性和维护性提高了

8.2.4  继承的深入讨论/细节问题

1) 子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问

2) 子类必须调用父类的构造器, 完成父类的初始化

3) 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过(怎么理解。) [举例说明]

4) 如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)

5) super 在使用时,必须放在构造器第一行(super 只能在构造器中使用)

6) super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器

7) java 所有类都是 Object 类的子类, Object 是所有类的基类. 8) 父类构造器的调用不限于直接父类!将一直往上追溯直到 Object 类(顶级父类)

9) 子类最多只能继承一个父类(指直接继承),即 java 中是单继承机制。

思考:如何让 A 类继承 B 类和 C 类? 【A 继承 B, B 继承 C】

10) 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系

8.3  super 关键字

8.3.1  基本介绍

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

8.3.2  基本语法

8.3.3  super 给编程带来的便利/细节

 8.3.4  super 和 this 的比较

8.4  方法重写/覆盖(override)

8.4.1  基本介绍

 8.4.2  注意事项和使用细节

8.5  面向对象编程-多态

8.5.1  多[多种]态[状态]基本介绍

        方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。

8.5.2  对象的多态 (核心,困难,重点)

 8.5.3  多态注意事项和细节讨论

8.6  Object 类详解

8.6.1  equals 方法

 8.6.2  如何重写 equals 方法

         应用实例: 判断两个 Person 对象的内容是否相等,如果两个 Person 对象的各个属性值都一样,则返回 true,反之 false。

//重写 Object 的 equals 方法
public boolean equals(Object obj) {
//判断如果比较的两个对象是同一个对象,则直接返回 true
    if(this == obj) {
        return true;
        }
    //类型判断
    if(obj instanceof Person) {//是 Person,我们才比较
        //进行 向下转型, 因为我需要得到 obj 的 各个属性
        Person p = (Person)obj;
        return this.name.equals(p.name) && this.age == p.age && this.gender == p.gender;
    }
    //如果不是 Person ,则直接返回 false
    return false;
}

8.6.3  hashCode 方法

 老韩的 6 个小结:
1) 提高具有哈希结构的容器的效率!
2) 两个引用,如果指向的是同一个对象,则哈希值肯定是一样的!
3) 两个引用,如果指向的是不同对象,则哈希值是不一样的
4) 哈希值主要根据地址号来的!, 不能完全将哈希值等价于地址。

5) 案例演示[HashCode_.java]: obj.hashCode() [测试:A obj1 = new A(); A obj2 = new A(); A obj3 = obj1]
6) 后面在集合,中 hashCode 如果需要的话,也会重写, 在讲解集合时,老韩在说如何重写 hashCode()。

8.6.4  toString 方法

1) 基本介绍
默认返回:全类名+@+哈希值的十六进制,【查看 Object 的 toString 方法】
子类往往重写 toString 方法,用于返回对象的属性信息
2) 重写 toString 方法,打印对象或拼接对象时,都会自动调用该对象的 toString 形式

3) 当直接输出一个对象时,toString 方法会被默认的调用, 比如 System.out.println(monster); 就会默认调用

public String toString() { //重写后,一般是把对象的属性值输出,当然程序员也可以自己定制
    return "Monster{" +
    "name='" + name + '\'' +
    ", job='" + job + '\'' +
    ", sal=" + sal +
"};

8.6.5  finalize 方法

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

老韩提示: 我们在实际开发中,几乎不会运用 finalize , 所以更多就是为了应付面试.

第10章  面向对象编程(高级部分)

10.1  类变量内存布局

10.1.1  static关键字

 10.1.2  什么是类变量

 10.1.3  如何定义类变量

10.1.4  如何访问类变量

 

 10.1.5  类变量使用注意事项和细节讨论

 10.1.6  类方法基本介绍

 10.1.7  类方法的调用

 10.1.8  类方法使用注意事项和细节讨论

10.2 理解 main 方法语法 

10.2.1   深入理解 main 方法

 特别提示:
1) 在 main()方法中,我们可以直接调用 main 方法所在类的静态方法或静态属性。
2) 但是,不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员。

10.3 代码块

10.3.1 基本介绍

10.3.2 基本语法

 10.3.3  代码块的好处

//老韩解读
//(1) 下面的三个构造器都有相同的语句
//(2) 这样代码看起来比较冗余
//(3) 这时我们可以把相同的语句,放入到一个代码块中,即可
//(4) 这样当我们不管调用哪个构造器,创建对象,都会先调用代码块的内容
//(5) 代码块调用的顺序优先于构造器.. 
{
    System.out.println("电影屏幕打开...");
    System.out.println("广告开始...");
    System.out.println("电影正是开始...");
};

10.3.4  代码块使用注意事项和细节讨论

 

10.4  final 关键字

10.4.1 基本介绍

 10.4.2 final 使用注意事项和细节讨论

10.5  抽象类

10.5.1  抽象类的介绍

 10.5.2  抽象类使用的注意事项和细节讨论

10.5.3  解决之道-抽象类快速入门’

10.6  接口

10.6.1  基本介绍

 10.6.2  案例

 10.6.3  注意事项和细节

 

10.6.4  实现接口 vs 继承类

 

 

10.7  常用类

10.7.1 内部类

        成员内部类、静态内部类、局部内部类、匿名内部类

特点:

  • 编译之后可生成独立的字节码文件
  • 内部类可直接访问外部类私有成员,而不破坏封装
  • 可为外部类提供必要的内部功能组件
// 身体
class Body{
  // 头部
  class Header{
    // 也会生成class文件
  }
}

10.7.2  成员内部类

  • 在类的内部定义,与实例变量、实例方法同级别的类
  • 外部类的一个实例部分,创建内部类对象时,必须依赖外部类对象
  • 当外部类、内部类存在重名属性时,会优先访问内部类属性
  • 成员内部类里不能定义静态成员、可以包含静态常量(final)
// 外部类
public class Outer{
  //实例变量
  private String name = "张三";
  private int age = 20;
  //内部类
  class Inner{
    private String address = "北京";
    private String phone = "110";
    private String name = "李四";
    
    //方法
    public void show(){
      //打印外部类属性 此时有重名属性name
      sout(Outer.this.name); // 张三
      sout(age);
      //打印内部类中的属性
      sout(name); // 李四
      sout(address);
      sout(phone);
    }
  }
}

// 测试类
public class Test{
  psvm(String[] args){
    // 创建外部类对象
    Outer outer = new Outer();
    // 创建内部类对象
    Inner inner = outer.new Inner();
    
    //一步到位
    Inner inner = new Outer(.new Inner();
                            
    inner.show();
  }
}

10.7.3  静态内部类

        不依赖外部类对象,可直接创建或通过类名访问,可声明静态成员。

// 外部类
public class Outer{
  //实例变量
  private String name = "xxx";
  private int age = 20;
  
  // 静态内部类,和外部类相同
  static class Inner{
    private String address = "上海";
    private String phone = "111";
    // 静态成员
    private static int count = 1000;
    
    //方法
    public void show(){
      // 调用外部类的属性
      // 1. 先创建外部类对象
      Outer outer = new Outer();
      // 2. 调用外部类对象的属性
      sout(outer.name);
      sout(outer.age);
      // 调用静态内部类的属性和方法
      sout(address);
      sout(phone);
      // 调用静态内部类的静态属性
      sout(Inner.count);
    }
  }
}

// 测试类
public class Test{
  psvm(String[] args){
    // 直接创建静态内部类对象
    Outer.Inner inner = new Outer.Inner();
                     
    inner.show();
  }
}

 10.7.4  局部内部类

  • 定义在外部类方法中,作用范围和创建对象范围仅限于当前方法
  • 局部内部类访问外部类当前方法中的局部变量时,因无法保障变量的生命周期与自身相同,变量必须修饰为final
  • 限制类的使用范围
// 外部类
public class Outer{
  //实例变量
  private String name = "刘德华";
  private int age = 35;
  
  //方法
  public void show(){
    // 定义局部变量
    String address = "sz";
    
    // 局部内部类:注意不能加任何访问修饰符
    class Inner{
      private String phone = "11234";
      private String email = "ldh@qq.com";
      
      public void show2(){
        // 访问外部类的属性
        sout(name); // 相当于 Outer.this.name
        sout(age);
        // 访问内部类的属性
        sout(this.phone);
        sout(this.email);
        
        // 访问局部变量 jdk1.7要求必须常量final、jdk1.8自动添加final
        
      }
    }
    // 创建局部内部类对象
    Inner inner = new Inner();
    inner.show2();
  }
}

// 测试类
public class Test{
  psvm(String[] args){
    // 创建外部类对象
    Outer outer = new Outer();
                     
    outer.show();
  }
}

 10.7.5  匿名内部类

  • 没有类名的局部内部类(一切特征都与局部内部类相同)
  • 必须继承一个父类或者实现一个接口
  • 定义类、实现类、创建对象的语法合并,只能创建一个该类的对象
  • 优点:减少代码量
  • 缺点可读性较差
// 使用匿名内部类优化(相当于创建了一个局部内部类)
Usb usb = new Usb(){ // Usb为一个接口
  @Override
  public void service(){
    sout("连接电脑成功,fan开始工作")
  }
};
usb.service();

10.7.6  Object类

  • 超类、基类,所有类的直接或间接父类,位于继承树的最顶层
  • 任何类,如没有书写extends显示继承某个类,都默认直接继承Object类,否则为间接继承
  • Object类中所定义的方法,是所有对象都具备的方法
  • Object类型可以存储任何对象
    • 作为参数,可接受任何对象
    • 作为返回值,可返回任何对象

10.7.8  getClass()方法

  • public final Class<?> getClass(){}
  • 返回引用中存储的实际对象类型
  • 应用:通常用于判断两个引用中实际存储对象类型是否一致
// 判断s1 和 s2是不是同一个类型
Class class1 = s1.getClass();
Class class2 = s2.getClass();
// getClass返回 class类型

10.7.9  hashCode()方法

  • public int hashCode(){}
  • 返回该对象的哈希码值
  • 哈希值根据对象的地址或字符串或数字使用hash算法计算出来的int类型的值
  • 一般情况下相同对象返回相同哈希码
s1.hashCode();
s2.hashCode();
// 自然不同
Student s3 = s1; // 此时s3的hashCode与s1相同

10.7.10  toString()方法

  • public String toSring(){}
  • 返回该对象的字符串表示(表现形式)
  • 可以根据程序需求覆盖该方法,如:展示对象各个属性值
sout(s1.toString()); // 直接打印包+类名+哈希值
// 重写 alt + enter + s
@override
public String toString(){
  return "Student [name = " + name + ", age = " + age + "]";
}

10.7.11  equals()方法

  • public boolean equals(Object obj){}
  • 默认实现为(this == obj), 比较两个对象地址是否相同
  • 可进行覆盖,比较两个对象的内容是否相同
// 判断两个对象是否相等
sout(s1.equals(s2)); // false

Student s4 = new Strudent("小明", 17);
Student s5 = new Strudent("小明", 17);
sout(s4.equals(s5)); // false 堆中地址不同

// 重写 改变其比较内容
/*
步骤  1. 比较两个应用是否指向同一个对象
     2. 判断obj是否为null
     3. 判断两个引用只想的实际对象类型是否一致
     4. 强制类型转换
     5. 依次比较各个属性值是否相同
*/
@override
public boolean equals(Object obj){
  // 1.
  if(this == obj){
    return true;
  }
  // 2.
  if(obj == null){
    return false;
  }
  // 3.
  // if(this.getClass() == obj.getClass()){
  //
  // }
  // instanceof 判断对象是否是某种类型
  if(obj instanceof Student){
    // 4.强制类型转换
    Student s = (Student)obj;
    // 5. 比较属性
    if(this.name.equals(s.getName()) && this.age == s.getAge()){
      return true;
    }
  }
  return false;
}

10.7.12  finalize()方法

  • 当对象被判定为垃圾对象时,由JVM自动调用此方法,用以标记垃圾对象,进入回收队列
  • 垃圾对象:没有有效引用指向此对象时,为垃圾对象
  • 垃圾回收:由gc销毁垃圾对象,释放数据存储空间
  • 自动回收机制:JVM的内存耗尽,一次性回收所有垃圾对象
  • 手动回收机制:使用System.gc();通知JVM执行垃圾回收
@Override
protected void finalize() throws Throwable{
  sout(this.name + "对象被回收了");
}

psvm(String[] args){
  Student s1 = new Student("aaa", 29); // 不是垃圾
  new Student("bbb", 30); // 是辣鸡 会被回收
  //回收垃圾
  System.gc();
  sout("回收垃圾"); 
  // 打印出 “回收垃圾 
  //         aaa对象被回收了”
}
  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值