本章内容:
1.如何创建一个标准的类 2.API的概述与使用 3.对象型数组 4.面向对象的三大特性 5.抽象类和抽象方法补充 6.接口补充 7.多态性的补充 8.final关键字
1.如何创建一个标准的类 一个标准的类通常要拥有下面四个部分:
所有的成员变量都要使用private关键字修饰
为每一个成员变量编写一堆Getter/Setter方法
编写一个无参数的构造方法
编写一个全参数的构造方法
举一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 package com.bytedance;public class Pokers { public static void main (String[] args) { Woman w1 = new Woman(); w1.setName("迪丽热巴" ); w1.setAge(18 ); System.out.println("姓名:" +w1.getName()+",年龄:" +w1.getAge()); System.out.println("========" ); Woman w2 = new Woman("古力娜扎" ,19 ); System.out.println("姓名:" +w2.getName()+",年龄:" +w2.getAge()); System.out.println("========" ); w2.setAge(20 ); System.out.println("修改年龄后~" +"姓名:" +w2.getName()+",年龄:" +w2.getAge()); } } class Woman { private String name; private int age; public Woman () { } public Woman (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; } }
运行结果: 姓名:迪丽热巴,年龄:18 ======== 姓名:古力娜扎,年龄:19 ======== 修改年龄后~姓名:古力娜扎,年龄:20
2. API的概述与使用 导包:import 包路径.类名称只有Java.lang包内的内容不需要导入,其余的API都要手动导入
3.对象型数组 对象型数组这一小节不仅能够温习如何创建一个最标准的类,也复习了有关于数组(数组长度不可改变)的一些操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 package com.bytedance;public class objectArray { public static void main (String[] args) { People[] people = new People[3 ]; People p1 = new People("迪丽热巴" , 18 ); People p2 = new People("古力娜扎" , 28 ); People p3 = new People("马尔扎哈" , 688 ); people[0 ] = p1; people[1 ] = p2; people[2 ] = p3; System.out.println(people[0 ]); System.out.println(people[1 ]); people[0 ].sayHello("陈浩东" ); } } class People { private String name; private int age; public People () { } public People (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; } public void sayHello (String lover) { System.out.println("大家好,我叫" + this .name + ",今年" + this .age + "岁了,喜欢" + lover); } }
4.面向对象的三大特性 面向对象的三大特性:继承,封装,多态 封装性在Java当中的体现:
方法(理解成python中的函数)就是一种封装
关键字private也是一种封装
一旦使用了private进行修饰,只能在本类中随意访问,但是,超出了本类范围就不能直接访问(间接访问private成员变量,就是定义一对getter,setter方法)
对于Getter来说,不能有参数,返回值类型与成员变量对应
对于Setter来说,不能有返回值,参数类型和成员变量对应
对于基本类型当中的Boolean值,Getter方法一定要携程isXXXX的形式,而SetXXX规则不变
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class Main { public static void main (String[] args) { Person ming = new Person(); ming.setName("Xiao Ming" ); ming.setAge(12 ); System.out.println(ming.getName() + ", " + ming.getAge()); } } class Person { private String name; private int age; public String getName () { return this .name; } public void setName (String name) { if (name == null || name.isBlank()) { throw new IllegalArgumentException("invalid name" ); } this .name = name.strip(); } public int getAge () { return this .age; } public void setAge (int age) { if (age < 0 || age > 100 ) { throw new IllegalArgumentException("invalid age value" ); } this .age = age; } }
5.抽象类和抽象方法补充 如果父类当中的方法不确定能实现什么具体的方法,那么这应该就是一种抽象方法(通俗的理解,比如求图形的面积计算方法,动物吃东西的方法。这里我们具体确定是什么图形,是三角形?还是正方形?,是比较抽象的一类概念)
抽象方法:就是加上abstract关键字,然后去掉大括号,直接分号结束 抽象类:抽象方法所在的类,必须是抽象类才行。在class之前写上abstract即可
如何使用抽象类和抽象方法:
不能直接创建new抽象对象
必须用一个子类来继承抽象父类
子类必须覆盖重写抽象父类当中的所有抽象方法(即子类去掉抽象方法的abstract关键字,然后补上方法体和大括号),否追编译无法通过
创建子类对象进行使用
抽象类中,可以有构造方法,是供子类创建对象时,初始化父类成员使用的
注意:在使用abstract关键字修饰抽象方法时不能使用private修饰,因为抽象方法必须被子类重写,而如果使用了private声明,则子类是无法重写的
6.接口 接口就是一种公共的规范标准。只要符合标准规范,就可以大家通用(比如插座,U盘)。 接口是一种引用数据类型,最重要的内容就是其中的抽象方法。
如何定义一个接口的格式: 1 2 3 public interface 接口名{ // 接口内容 }
接口内容 在任何版本中,接口都能定义抽象方法
2.1 常量
接口当中也可以定义“成员变量”,但必须使用public static final
三个关键字进行修饰。从效果上看,这就是接口的常量 格式: public static final 数据类型 常量名称 = 数据值
PS:
一旦使用final关键字,就说明不可变
接口当中的常量必须赋值
接口当中的常量的命名规范:使用完全大写的字母,用下划线进行分隔
调用接口名的常量方法:接口名.常量名
2.2 抽象方法
接口中最重要的时抽象方法 格式:
1 [public] [abstract] 返回值类型 方法名(参数){方法体}
注意:实现类必须覆盖重写接口的所有的抽象方法,除非实现类是抽象的
2.3 默认方法(接口中的默认方法,可以解决接口升级的问题)
1 2 3 4 5 6 7 8 格式: public default 返回值类型 方法名(参数列表){ 方法体 // 默认方法里面可以有方法体 } 使用: 1.接口的默认方法,可以通过接口实现类对象,直接调用 2.接口的默认方法,也可以被接口实现类进行覆盖重写
2.4 静态方法
创建格式:
1 2 3 4 5 格式: public static 返回值类型 方法名称(参数列表){ 方法体 } tips:就是将abstract 或者default换成static即可,带上方法体。
注意: 1.不能通过实现类的的对象来调用接口当中的静态方法 2.正确调用方式:接口名.静态方法名(参数)。与之前学习的static静态方法的调用方式(类名称.静态方法)一样
2.5 私有方法
问题描述:我们需要一个共有方法,用来解决两个默认方法之间重复代码的问题。但是这个共有方法不应该让实现类使用,应该是私有化的
解决方案:从java9开始,接口当中允许定义私有方法 Ⅰ. 普通私有方法,解决多个默认方法之间重复代码问题
1 2 3 private 返回值类型 方法名(参数列表){ 方法体 }
Ⅱ. 静态私有方法,解决多个静态方法之间的重复代码问题
1 2 3 private static 返回值类型 方法名(参数列表){ 方法体 }
接口使用步骤
接口不能直接使用,必须有一个“实现类”来“实现”该接口
格式:public class 实现类名 implements 接口名称{…}
接口的实现类必须重写接口中所有的抽象方法(即去掉abstract关键字,加上方法体和大括号)
创建实现类的对象,进行使用(即直接 new 实现类的对象,才能使用)。
接口是没有静态代码块或者构造方法的
Java的类只能单继承,但接口可以implement多个接口 接口的小结:
7.多态性的补充 代码当中体现多态性,其实就是一句话:父类引用指向子类对象(extends,implement是体现多态性的前提)
格式:父类引用指向子类对象(即以左父右子 ) 父类名称. 对象名 = new 子类名称(); 或者: 接口名称. 对象名 = new 实现类名称()
在多态的代码,父类引用指向子类对象是,即 Fu obj = new Zi()
中:
成员方法的访问规则: 看new的是谁(即看右边),就优先用谁,没有就向上一级找
成员变量的访问规则: Ⅰ. 直接通过对象名称访问成员变量,看等号左边是谁,优先用谁 Ⅱ. 间接通过成员方法访问成员变量:看该方法属于谁(假如子类覆盖重写了父类,则通过访问子类调用成员方法来访问成员变量),就优先用谁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package com.Alibaba;public class Mult { public static void main (String[] args) { Fu1 fu1 = new Zi1(); System.out.println(fu1.num); fu1.showNum(); System.out.println("====" ); fu1.showNum(); } } class Fu1 { int num = 10 ; public void showNum () { System.out.println(num); } } class Zi1 extends Fu1 { int num = 20 ; @Override public void showNum () { System.out.println(num); } }
对象的向上转型
对象的向上转型,其实就是多态的写法;
格式:父类名称 对象名 = new 子类名称()
1 2 Animal animal = new Cat(); 创建了一只猫,当作中午来看,是没问题的。
含义:右侧创建一个子类对象,把它当作父类来看待 注意事项;向上转型一定是安全的,从小范围转向了大范围。从小范围的猫,向上转换成为了范围更大的动物
对象的向下转型
对象的向下转型,其实是一个【还原】的动作
若想要实现向下转型的前提是有一个向上转型成功的对象名
格式:子类名称 对象名 = (子类名称) 父类对象名
1 2 Animal animal = new Cat(); //向上转型成功,将本来是猫,向上转型成为动物 Cat cat = (Cat) animal; // 本来是猫,已经被当做动物了,还原回来成为了原本的猫
注意事项; Ⅰ. 必须保证对象本来创建的时候,就是猫,才能向下转型成为猫 Ⅱ. 如果对象创建的时候本来不是猫。现在非要向下转型成为猫,就会报错(ClassCastException)
用instanceof关键字判断一个父类的引用对象,本来是什么子类?
格式:对象名 instanceof 类名称
完整的源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 public class InstanceofDemo { public static void main (String[] args) { Animal animal = new Cat(); animal.eat(); if (animal instanceof Dog){ Dog dog = (Dog) animal; dog.watchHOuse(); } if (animal instanceof Cat){ Cat cat = (Cat) animal; cat.catchMOnth(); } getMeAPet(new Dog()); } public static void getMeAPet (Animal animal) { if (animal instanceof Dog){ Dog dog = (Dog) animal; dog.watchHOuse(); } if (animal instanceof Cat){ Cat cat = (Cat) animal; cat.catchMouse(); } } } abstract class Animal { public abstract void eat () ; } class Cat extends Animal { @Override public void eat () { Systeam.out.println("猫吃鱼" ); } public void catchMouse () { Systeam.out.println("猫抓老鼠吃" ); } } class Dog extends Animal { @Override public void Dog () { Systeam.out.println("狗吃骨头" ); } public void watchHouse () { Systeam.out.println("狗正在看家" ); } }
8.final关键字 final关键字代表最终,不可改变,常见的四种方法:
当final关键字用来修饰一个类时(表示当前这个类不能有任何子类,即无法继承) ,格式: public final class 类名称{属性和方法}
当final关键字修饰一个方法时,这个方法就是最终方法,也无法被覆盖重写 ,格式: 修饰符 final 返回值类型 方法名(参数列表){方法体}
一般局部变量:int age = 18; int age = 20(对于普通变量来说可以任意重新赋值) final最终变量:一旦使用final用来修饰局部变量,那么这个变量就无法更改:final int age = 18
对于成员变量来说,如果使用final关键字修饰,那么这个变量也照样不可变 由于成员变量具有默认值,所以采用final之后必须要手动赋值,不会再给默认值 对于final的成员变量,要么使用直接赋值,要么通过构造方法赋值,二者选其一 必须保证类当中的所有重载的构造方法,都最终会对final的成员变量进行赋值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Person {private final String name; public Person () {name = "关晓彤" } public Person (String name) {this .name = name;} public String gerName () {return name;} }
PS: 对于类和方法来说,abstract与final关键字不能同时使用,因为自相矛盾