> 文章列表 > 从零开始学JAVA(05):面向对象编程--04

从零开始学JAVA(05):面向对象编程--04

从零开始学JAVA(05):面向对象编程--04

一、StringBuilder

StringBuilder是一个非常方便的用来处理和拼接字符串的类,它和string不同的是,它是可变的

package com.lcy.learn;public class LearnStringBuilder {public static void main(String[] args) {// StringBuilder首先是可变的// 而且对它进行操作的方法,都会返回this的自引用。这样我们就可以一直点下去,对String进行改造StringBuilder strBuilder = new StringBuilder();long longVal = 123145151;strBuilder.append(true).append("abc").append(longVal);System.out.println(strBuilder.toString());System.out.println(strBuilder.reverse().toString());System.out.println(strBuilder.reverse().toString());System.out.println(strBuilder.toString());System.out.println(strBuilder.delete(0, 5).toString());System.out.println(strBuilder.insert(0, "是多少").toString());}
}

二、继承

  • 子类继承了父类的方法和属性
  • 使用子类的引用可以调用父类的共有方法
  • 使用子类的引用可以访问父类的共有属性
  • 就好像子类的引用可以一物二用,既可以当做父类的引用使用,又可以当做子类的引用使用

1、Child 

package com.lcy.learn;// 继承的语法就是在类名后面使用extends加要继承的类名
// 被继承的类叫做父类
// 继承者叫做子类
// java中只允许一个类有一个直接的父类,即所谓的单继承
// 别的类也可以继承子类
// TODO: 子类继承了父类什么呢?所有的属性和方法
// TODO: 但是子类不能访问父类的private的成员(包括方法和属性)
public class Child extends Parent {public Child(int age, String name, String hobby) {super(age, name, hobby);}
}

2、Parent

package com.lcy.learn;public class Parent {private int age;private String name;public String hobby;Parent(int age, String name, String hobby) {this.age = age;this.name = name;this.hobby = hobby;}public void sayHi () {System.out.println(this.name + "说:你好,我是" + this.name + ",我的爱好是" + this.hobby);}
}

3、覆盖(多态)

  • 通过使用和父类方法签名一样,返回值也一样的方法,可以让子类覆盖掉父类的方法
  • 子类并不是单纯的把父类的方法拿过来,而是可以通过覆盖的方式形成自己独有的方法
public class Child extends Parent {private String grade;public Child(int age, String name, String hobby, String grade) {super(age, name, hobby);this.grade = grade;}@Overridepublic void sayHi() {super.sayHi();System.out.println("我现在上"+this.grade+"了");}
}

super:子类和父类沟通的桥梁,但并不是父类的引用

  • 子类对象里可以有一个特殊的父类的对象,这个父类对象和子类对象之间通过super关键字来沟通。 
  • 使用super可以调用父类的public属性,但是super不是一个引用
  • 使用super调用父类的构造方法,必须是子类构造方法的第一句
  • super调用构造方法,不可以使用super访问父类的属性和方法, 不可以使用子类成员变量和方法,可以使用静态变量和方法

4、父类和子类的引用赋值关系 

  • 可以用子类的引用给父类的引用赋值,也就是说,父类的引用可以指向子类的对象
  • 但不能让子类的引用指向父类的对象。因为父类并没有子类的属性和方法
  • 因为子类继承了父类的方法和属性,所以父类的对象能做到的,子类的对象肯定能做到
  • 父类的引用,可以指向子类的对象,即可以用子类(或者子类的子类)的引用给父类的引用赋值

import com.lcy.learn.Child;
import com.lcy.learn.Parent;public class Main {public static void main(String[] args) {// 可以用子类的引用给父类的引用赋值,也就是说,父类的引用可以指向子类的对象Child childClassExample = new Child(18, "莉莉", "躺平", "高三");Parent parentClassExample = childClassExample;Parent parentClassExample1 = new Child(18, "莉莉1", "躺平", "高三");// 但不能让子类的引用指向父类的对象。因为父类并没有子类的属性和方法// Child errorDefinition = new Parent(18, "莉莉1", "躺平", "高三");// 如果确定一个父类的引用指向的对象,实际上就是一个子类的对象(或者子类的子类的对象),可以强制类型转换Child parentDefinitionChild = (Child) parentClassExample1;// 父类的引用,可以指向子类的对象,即可以用子类(或者子类的子类)的引用给父类的引用赋值}
}

三、多态

1、重载总结:静态多态,调用的方法和参数实际指向的对象无关,只和引用本身的类型相关;

2、因为调用时参数类型是确定的,所以,在编译期间就可以明确的知道哪个方法会被调用。如果有多种可能,则会有编译错误;

3、如果没有类型完全匹配的候选,则根据类型的继承关系向下撸着找。找到最贴近参数类型的那个方法;

4、无论是静态方法,还是成员方法,重载寻找方法的顺序是一样的;

5、覆盖:动态多态

四、instanceof操作符

1、instanceof操作符可以判断一个引用指向的对象是否是某一个类型或者其子类,是则返回true,否则返回false

2、null永远返回的是false

五、继承专属的访问控制:protected

1、protected可见性:default + 对子类可见;

2、可以覆盖被protected修饰的属性或方法,但不能让可见性更低;

六、final修饰符

1、用final修饰类:则这个类不可以被继承 

2、用final修饰成员变量:那么这个成员变量不能被修改,只能在构造方法中进行赋值

3、用final修饰静态变量:此静态变量只能被赋值一次,切必须赋值

4、构造方法不能用final修饰

5、用final修饰方法:此方法不可以被子类覆盖

6、用final修饰形参:在方法体中这个形参不能被赋值了

7、用final修饰局部变量:不能被重新赋值,只能被赋值一次,切必须赋值

8、用final修饰引用:一定要赋值,且只能赋值一次,引用内部的非final是可变的

9、用final修饰数组:不能改变数组的引用,但是可以改变数组中的某一项

七、继承里的静态方法 

1、静态方法可以被继承

2、子类可以定义和父类签名一样的方法,但是返回值必须和父类一致

八、Object类

 1、所有的类,都直接或间接的继承于Object类;

九、hashCode和equals方法初探

1、hashCode可以翻译为哈希码,或者散列码。应该是一个表示对象的特征值的int整数

2、equals方法应该用来判断两个对象从逻辑上是否相等 

3、hashCode和equals方法时最常被覆盖的两个方法,覆盖的原则是,equals为true,那么hashCode的值一定相等,这是约定成俗的。即equals位true是hashCode相等的充分非必要条件,hashCode相等时equals为true的必要不充分条件

package com.lcy;import java.math.BigDecimal;
import java.util.Objects;public class publicAndPrivate {int age = 18;private BigDecimal money;// 这是一个构造方法public publicAndPrivate(BigDecimal money) {this.money = money;System.out.println("你出生了,你有" + this.money + "元");}public void makeMoney (BigDecimal money) {this.money = this.money.add(money);System.out.println("你今天当了一天打工人,你赚了"+money+"元,"+"你现在有"+this.money+"元");}public void consumption (BigDecimal money) {this.money = this.money.subtract(money);System.out.println("你今天出去潇洒了一天,你花了"+money+"元,"+"你现在有"+this.money+"元");}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (!(o instanceof publicAndPrivate)) return false;publicAndPrivate that = (publicAndPrivate) o;return age == that.age && Objects.equals(money, that.money);}@Overridepublic int hashCode() {return Objects.hash(age, money);}
}

String的equals方法 

package com.lcy;import java.util.Scanner;public class StringEqualsTest {public static void main(String[] args) {String s1 = "aaabbb";String s2 = "aaa" + "bbb";// Java对字符串做了优化,如果新创建的字符串在之前已经创建过了,就直接返回这个String的引用System.out.println("用==比较S1和S2," + (s1 == s2)); // trueSystem.out.println("用equals比较S1和S2," + s1.equals(s2)); // true// 打乱Java对String的优化Scanner scanner = new Scanner(System.in);System.out.println("请输入s1");s1 = scanner.nextLine();System.out.println("请输入s2");s2 = scanner.nextLine();System.out.println("用==比较S1和S2," + (s1 == s2)); // falseSystem.out.println("用equals比较S1和S2," + s1.equals(s2)); // true}
}