- List item
JavaStudy—B站hsp
一、java面向对象回顾
1.IDEA使用
1.快捷键
2.包的本质和命名规范
2.访问修饰符
3.1基本介绍
java 提供四种访问控制修饰符号,用于控制方法和属性(成员变量)的访问权限(范围):
\1) 公开级别:用 public 修饰,对外公开
\2) 受保护级别:用 protected 修饰,对子类和同一个包中的类公开
\3) 默认级别:没有修饰符号,向同一个包的类公开.
\4) 私有级别:用 private 修饰,只有类本身可以访问,不对外公开.
3.2种访问修饰符的访问范围
3.面向对象编程三大特征
3.1基本介绍
面向对象编程有三大特征:封装、继承和多态。
3.2封装介绍
封装就是把抽象出的数据**[属性]**和对数据的操作[方法]封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作[方法],才能对数据进行操作。
3.2.1封装的理解和好处
//(1)隐藏实现细节:方法(连接数据库)<--调用(传入参数..)
//(2)可以对数据进行验证,保证安全合理
Person {name,age}
Person p = new Person();
p.name = "jack";
p.age = 12;
3.2.2封装的实现步骤 (三步)
3.3面向对象编程-继承
3.3.1.为什么需要继承
1.提高代码的复用性
2.当两个类具有相同的特征(属性)和行为(方法)时,可以相同的部分抽取出来放到一个类中作为父类,其他两个类继承这个父类。
3.3.2.继承基本介绍和示意图
继承可以解决代码复用,让我们的编程更加靠近人类思维.当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过 extends 来声明继承父类即可。画出继承的示意图
3.3.3.继承的基本语法
3.3.4继承给编程带来的便利
-
代码的复用性提高了
-
代码的扩展性和维护性提高了
3.3.5继承的深入讨论/细节问题
-
子类继承了所有的属性和方法,非私有的属性和方法可以在子类直接访问, 但是私有属性和方法不能在子类直接访问,要通过父类提供公共的方法去访问;
-
子类必须调用父类的构造器, 完成父类的初始化 ;
-
当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无 参构造器,则必须在子类的构造器中用 super 去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译 不会通过(怎么理解。) [举例说明]
-
如果希望指定去调用父类的某个构造器,则显式的调用一下 : super(参数列表)
-
super 在使用时,必须放在构造器第一行(super 只能在构造器中使用)
-
super() 和 this() 都只能放在构造器第一行,因此这两个方法不能共存在一个构造器
-
java 所有类都是 Object 类的子类, Object 是所有类的基类.
-
父类构造器的调用不限于直接父类!将一直往上追溯直到 Object 类(顶级父类)
-
子类最多只能继承一个父类(指直接继承),即 java 中是单继承机制。
思考:如何让 A 类继承 B 类和 C 类? 【A 继承 B, B 继承 C】
- 不能滥用继承,子类和父类之间必须满足 is-a 的逻辑关系
3.3.4子类创建的内存布局
3.3.5 super 给编程带来的便利/细节
3.3.6 super 和 this 的比较
3.3.7方法重写/覆盖(override)
1.基本介绍
2.注意事项和使用细节
3.对方法的重写和重载做一个比较
3.4多[多种]态[状态]基本介绍
方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的。
3.4.1多态的具体体现
- 方法的多态 PloyMethod.java
重写和重载就体现多态 [案例说明:]
public class PloyMethod {
public static void main(String[] args) {
//方法重载体现多态
A a = new A(); //这里我们传入不同的参数,就会调用不同 sum 方法,就体现多态
System.out.println(a.sum(10, 20));
System.out.println(a.sum(10, 20, 30));
//方法重写体现多态
B b = new B();
a.say();
b.say();
}
}
class B { //父类
public void say() {
System.out.println("B say() 方法被调用...");
}
}
class A extends B {//子类
public int sum(int n1, int n2){
//和下面 sum 构成重载
return n1 + n2;
}
public int sum(int n1, int n2, int n3){
return n1 + n2 + n3;
}
public void say() {
System.out.println("A say() 方法被调用...");
}
}
- 对象的多态 (核心,困难,重点)
3.4.2多态注意事项和细节讨论
多态的前提是:两个对象(类)存在继承关系
3.4.3java 的动态绑定机制(非常非常重要.)
Java 重要特性: 动态绑定机制
二、 面向对象高级部分
(一)类变量(静态变量)
无论jdk版本如何,记住一点:static静态变量被对象共享
不管static变量在哪里,共识(1)static变量是同一个类所有对象共享(2)static在类加载的时候就生成了。
1.什么是类变量
类变量也叫静态变量/静态属性,是该类的所有对象共享的变量,任何一个类的对象去访问它时,取到的都是相同的值,同样的任何一个该类的对象去修改它时,修改的也是同一个变量。
2.如何定义类变量
**定义语法:**访问修饰符 static 数据类型 变量名(推荐)
static 访问修饰符 数据类型 变量名
3.如何访问类变量
类名.类变量名(推荐)
对象名.类变量名【静态变量的访问修饰符的访问权限和范围 和 普通属性时一样的。】
代码示例:
public class VisitStatic {
public static void main(String[] args) {
//类名.类变量名
//说明:类变量是随着类的加载而创建,所以即使没有创建对象实例也可以访问
System.out.println(A.name);
//通过对象名.类变量名
A a = new A();
System.out.println(a.name);
}
}
class A{
//类变量
//类变量的访问,必须遵守 相关的访问权限.
public static String name = "覃波";
(二)类方法/静态方法
1.基本介绍
/**
* 学生收费
*/
public class StaticMethod {
public static void main(String[] args) {
//创建两个对象交学费
Student student1 = new Student("小明");
student1.payFee(2000);
Student student2 = new Student("小红");
student2.payFee(3000);
//Student.payFee(500); 通过类名.类方法 也可以访问 也会该改变类变量fee的值
//输出当前的总学费
Student.showFee();
//如果我们希望不创建实例,也可以调用某个方法(即当做工具来使用)
//这时,把方法做成静态方法时非常合适
System.out.println("9开平方的结果是:" + Math.sqrt(9));
//调用MyTools中的类方法使用和上面Math中的aqrt一样的情况
System.out.println(MyTools.calSum(10, 15));
}
}
//开发自己的工具类.可以将方法做成静态的,方便调用
class MyTools{
//求出两个数之和
public static double calSum(double n1,double n2){
return n1+n2;
}
}
class Student{
//普通成员
private String name;
//定义一个静态变量,来积累学生的学费
public static double fee;
public Student(String name) {
this.name = name;
}
//说明
//1.当方法使用了static修饰后,该方法就是静态方法
//2.静态方法就可以访问静态属性
public static void payFee(double fee){
Student.fee += fee;
}
public static void showFee(){
System.out.println("总学费:" + Student.fee);
}
}
2.类方法注意事项
public class StaticMethodDetail {
public static void main(String[] args) {
}
}
class D{
private int n1 = 100;
private static int n2 = 200;
public void say(){ //非静态方法/普通方法
}
//静态方法/类方法
public static void hi(){
//类方法中不允许使用和对象有关的关键字
//比如 this 和 super。普通方法(成员方法)可以
// System.out.println(this.n1);
}
//类方法(静态方法)中 只能访问 静态变量 或静态方法
// 口诀:静态方法只能访问静态成员.
public static void hello(){
System.out.println(n2);
System.out.println(D.n2);
//System.out.println(D.n1);//不能使用
hi();//静态方法ok
// say();错误
}
//普通成员方法,既可以访问 非静态成员,也可以访问静态成员
//小结: 非静态方法可以访问 静态成员和非静态成员
public void ok() {
//非静态成员
System.out.println(n1);
say(); //静态成员
System.out.println(n2);
hello(); }
}
2.1练习题
1
2
class Person { //StaticExercise02.java 2min 时间
private int id;
private static int total = 0;
public static int getTotalPerson() {
//id++;//错误, 注销
return total;
}
public Person() {//构造器
total++; //total = 1
id = total;//id = 1
}
}
public class TestPerson {
public static void main(String[] args) {
System.out.println("Number of total is " +Person.getTotalPerson()); //0
Person p1 = new Person();
System.out.println( "Number of total is "+ Person.getTotalPerson()); //1
}
}
3
class Person { //StaticExercise03.java 2min 看
private int id;
private static int total = 0;
public static void setTotalPerson(int total){
// this.total = total;//错误,因为在 static 方法中,不可以使用 this 关键字
Person.total = total;
}
public Person() {
//构造器
total++; id = total; }}
public class TestPerson {
public static void main(String[] args) {
Person.setTotalPerson(3);
new Person();
//最后 total 的值就是 4
} }小结:记住两句话 (1) 静态方法,只能访问静态成员 (2) 非静态方法,可以访问所有的成员 (3) 在编写代码时,仍然要遵守访问权限规则
小结:记住两句话 (1) 静态方法,只能访问静态成员 (2) 非静态方法,可以访问所有的成员 (3) 在编写代码时,仍然要遵守访问权限规则
(三)main方法
1.深入理解main方法
解释main方法的形式:public static void main(String[] args){}
- main方法是虚拟机在调用
- java虚拟机需要调用main()方法,所以该方法的访问权限必须是public
- java虚拟机在执行main()方法时不必创建对象,所以该方法必须是static
- 该方法接收String类型的数组参数,该数组中保存执行java命令时传递给所运行的类的参数,案例演示,接受参数。
- java 执行的程序 参数1 参数2 参数3
特别提示:
-
在 main()方法中,我们可以直接调用 main 方法所在类的静态方法或静态属性。
-
但是,不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员
(四)代码块
1.基本介绍
代码块又称为初始化块,属于类中的成员【即 是类的一部分】,类似于方法,将逻辑语句封装在方法体中,通过{}包围起来。
但和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不通过对象或类显示调用,而是类加载时,或创建对象时隐式调用。
2.基本语法
[修饰符]{
代码
}
说明注意:
- 修饰符 可选,要写的话只能写static
- 代码块分为两类,使用static 修饰的叫静态代码块,没有static修饰的,叫普通代码块/非静态代码块
- 逻辑语句可以为任何逻辑语句(输入、输出、方法调用、循环、判断等)
- **;**可以写上,也可以省略。
3.代码块的好处和案例演示
-
相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化的操作。
-
场景:如果多个构造器中有重复的语句,可以抽取到初始化块中,提高代码的复用性
-
案例
谨记:代码块调用的顺序优先于构造器…
public class CodeBlock01 {
public static void main(String[] args) {
Movie movie = new Movie("你哈");
System.out.println("==============================");
Movie movie1 = new Movie("你哈",200,"王仁");
}
}
class Movie{
private String name;
private double price;
private String director;
//3 个构造器-》重载
//1.下面三个构造器都有相同的语句
//2.这样看起来代码比较冗余
//3.这时我们可以把相同的语句,放入到一个代码块中,即可
//4.这样当我们不管调用哪个构造器,创建对象,都会先调用代码块的内容
//5.代码块调用的顺序优先于构造器..
{
System.out.println("电影显示器打开");
System.out.println("电影广告");
System.out.println("电影正式开始");
}
public Movie(String name) {
// System.out.println("电影显示器打开");
// System.out.println("电影广告");
// System.out.println("电影正式开始");
System.out.println("Movie(String name) 被调用...");
this.name = name;
}
public Movie(String name, double price) {
/*System.out.println("电影显示器打开");
System.out.println("电影广告");
System.out.println("电影正式开始");*/
this.name = name;
this.price = price;
}
public Movie(String name, double price, String director) {
// System.out.println("电影显示器打开");
// System.out.println("电影广告");
// System.out.println("电影正式开始");
System.out.println("Movie(String name, double price, String director) 被调用...");
this.name = name;
this.price = price;
this.director = director;
}
}
4.代码块使用注意事项和细节
- static代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行,并且只会执行一次。如果是普通代码块,每创建一个对象就执行。
- 类什么时候被加载【重要】
①创建对象实例时
②创建子类对象实例时,父类也会被加载
③使用类的静态成员时(静态属性,静态方法)
-
普通的代码块,在创建对象实例时,会被隐式的调用。被创建一次,就会调用一次。 如果只是使用类的静态成员时,普通代码块并不会执行。
小结:1.static代码块是类加载时,执行,只会执行一次
2.普通代码块是在创建对象时调用的,创建一次,调用一次
3.类加载的3种情况,需要记住。案例演示:
public class CodeBlockDetail01 {
public static void main(String[] args) {
//类被加载的情况举例
// 1. 创建对象实例时(new)
//AA aa = new AA();
//2. 创建子类对象实例,父类也会被加载, 而且,父类先被加载,子类后被加载
//AA aa = new AA();
//3. 使用类的静态成员时(静态属性,静态方法)
//System.out.println(Cat.n1);
//DD dd = new DD();
//DD dd1 = new DD();
//普通的代码块,在创建对象实例时,会被隐式的调用。
// 被创建一次,就会调用一次。
// 如果只是使用类的静态成员时,普通代码块并不会执行
System.out.println(DD.n1);//8888, 静态模块块一定会执行
}
}
class DD {
public static int n1 = 8888;//静态属性
// 静态代码块
static {
System.out.println("DD 的静态代码 1 被执行...");
}
//普通代码块, 在 new 对象时,被调用,而且是每创建一个对象,就调用一次
//可以这样简单的,理解 普通代码块是构造器的补充
{
System.out.println("DD 的普通代码块...");
}
}
class Animal {
//静态代码块
static {
System.out.println("Animal 的静态代码 1 被执行...");
}
}
class Cat extends Animal{
public static int n1 = 999;//静态属性
// 静态代码块
static {
System.out.println("Cat 的静态代码 1 被执行...");
}
}
class BB{
static {
System.out.println("BB 的静态代码 1 被执行...");
}
}
class AA extends BB{
static {
System.out.println("AA 的静态代码 1 被执行...");
}
}
-
创建一个对象时,在一个类调用顺序是:(重点,难点):
①调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样,如果多个静态代码块和多个静态变量初始化,则按他们的顺序调用)(再次提示,静态代码块只随类加载一次)
②调用普通代码块和普通属性初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果多个普通代码块和多个普通变量初始化,则按他们的顺序调用)(再次提示,普通代码块只随创建对象实例加载)
③调用构造方法
代码演示:
public class CodeBlockDetail02 {
public static void main(String[] args) {
A a = new A();//1.getN1被调用。。2.A 静态代码块
B b = new B();//3.getN2被调用。。4.B 静态代码块
System.out.println("===========");
new A();//静态代码块只执行一次
new B();//getN2被调用。. B 静态代码块 B 的构造方法
}
}
class A{
//静态属性的初始化
private static int n1 = getN1();
static {//静态代码块
System.out.println("A 静态代码块");
}
public static int getN1(){
System.out.println("getN1被调用。。");
return 100;
}
}
class B{
public B(){
System.out.println("B 的构造方法");
}
//普通属性初始化
private int n2 = getN2();
{
System.out.println("B 静态代码块");
}
public int getN2(){
System.out.println("getN2被调用。。");
return 101;
}
}
- 构造器 的最前面其实隐含了super()和调用普通代码块,新写一个类演示【截图+说明],静态相关的代码块,属性初始化,在类加载时,就执行完毕因此是优先于构造器和普通代码块执行的。 CodeBlockDetail03.java
代码演示:
public class CodeBlockDetail03 {
public static void main(String[] args) {
new BBB();// 1.AAA 的普通代码块被调用 2.AAA的构造器被调用 3.BBB普通代码块 4.BBB的构造器被调用
}
}
class AAA{
public AAA(){
System.out.println("AAA的构造器被调用");
}
{
System.out.println("AAA 的普通代码块被调用");
}
}
class BBB extends AAA{
{
System.out.println("BBB普通代码块");
}
public BBB(){
//1.super();
//2.调用本类的普通代码块
System.out.println("BBB的构造器被调用");
}
}
-
我们看一下创建一个子类对象时(继承关系),他们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下:
①父类的静态代码块和静态属性(优先级一样,按定义顺序执行)
②子类的静态代码块和静态属性(优先级一样,按定义顺序执行)
③父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
④父类的构造方法
⑤子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)
⑥子类的构造方法 //面试题
AAAAA extends BBBBB类演示[10Min]55 CodeBlockDetail04.java -
静态代码块只能直接调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员。学习比较麻烦,工作轻松
代码演示:
public class CodeBlockDetail04 {
public static void main(String[] args) {
//老师说明
//(1) 进行类的加载
//1.1 先加载 父类 A02 1.2 再加载 B02
//(2) 创建对象
//2.1 从子类的构造器开始
//new B02();
//对象 new C02();
}
}
class A02{ //父类
private static int n1 = getVal01();
static {
System.out.println("A02 的一个静态代码块..");//(2)
}
{
System.out.println("A02 的第一个普通代码块..");//(5)
}
public int n3 = getVal02();//普通属性的初始化
public static int getVal01() { System.out.println("getVal01");//(1)
return 10;
}
public int getVal02(){
System.out.println("getVal02");//(6)
return 10;
}
public A02() {//构造器
//隐藏
//super()
//普通代码和普通属性的初始化......
System.out.println("A02 的构造器");//(7)
} }
class C02 {
private int n1 = 100;
private static int n2 = 200;
private void m1() {
}
private static void m2() {
}
static {
//静态代码块,只能调用静态成员
//System.out.println(n1);错误
System.out.println(n2);//ok
//m1();
//错误 m2();
}
{ //普通代码块,可以使用任意成员
System.out.println(n1);
System.out.println(n2);//ok
m1();
m2();
} }
class B02 extends A02 {
private static int n3 = getVal03();
static {
System.out.println("B02 的一个静态代码块..");//(4)
}
public int n5 = getVal04();
{
System.out.println("B02 的第一个普通代码块..");//(9)
}
public static int getVal03() {
System.out.println("getVal03");//(3)
return 10;
}
public int getVal04() { System.out.println("getVal04");//(8)
return 10;
}
//一定要慢慢的去品..
public B02() {//构造器
//隐藏了
//super()
//普通代码块和普通属性的初始化...
System.out.println("B02 的构造器");//(10)
// TODO Auto-generated constructor stub } }
(五)单例设计模式
1.什么是设计模式
2.什么是单例模式
单例(单个的实例)
- 所谓类的单例设计模式,就是采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类提供一个能取得其对象实例的方法。
- 单例模式有两种:1.饿汉式 2.懒汉式
2.1单例模式应用实例
2.2饿汉式vs懒汉式
2.3代码演示:
饿汉式:
/**
* 演示饿汉式-单例模式
*/
public class SingleTon01 {
public static void main(String[] args) {
// GirlFriend xh = new GirlFriend("小红");
// GirlFriend xb = new GirlFriend("小白");
//直接通过方法获取对象
GirlFriend instance = GirlFriend.getInstance();
System.out.println(instance);
GirlFriend instance2 = GirlFriend.getInstance();
System.out.println(instance2);//只会出现一个对象
System.out.println(instance == instance2);
}
}
//有一个类, GirlFriend
// 只能有一个女朋友
class GirlFriend{
private String name;
//为了能够在静态方法中,返回 gf 对象,需要将其修饰为 static
private static GirlFriend girlFriend = new GirlFriend("小甜甜");
//如何保障我们只能创建一个 GirlFriend 对象
//步骤
//1.将构造器私有化
//2.在类的内部直接创建
private GirlFriend(String name) {
this.name = name;
}
public static GirlFriend getInstance(){
return girlFriend;
}
@Override
public String toString() {
return "GirlFriend{" +
"name='" + name + '\'' +
'}';
}
}
懒汉式:
/**
* 演示懒汉式 -单例模式
*/
public class SingleTon02 {
public static void main(String[] args) {
Cat cat = Cat.getInstance();
System.out.println(cat);//Cat{name='猫猫'}
//再次调用getInstance()
Cat cat1 = Cat.getInstance();
System.out.println(cat1);//Cat{name='猫猫'}
System.out.println(cat ==cat1); //ture
}
}
//希望在程序运行中,只能创建一个Cat对象
//使用单例模式
class Cat {
private String name;
private static Cat cat;
//步骤
//1.构造器私有化
//2.定义一个atatic静态属性对象
//3.提供一個 public 的 static 方法,可以返回一個 Cat 對象
//4.
public Cat(String name) {
this.name = name;
}
public static Cat getInstance(){
if (cat == null){
cat = new Cat("猫猫");
}
return cat;
}
@Override
public String toString() {
return "Cat{" +
"name='" + name + '\'' +
'}';
}
}
(六)Final关键字
1.基本介绍
代码演示:
/**
* Final关键字
*/
public class Final01 {
public static void main(String[] args) {
E e = new E();
//e.TAX_RATE =0.09; final修饰属性 常量无法更改
}
}
//如果我们要求 A 类不能被其他类继承
// 可以使用 final 修饰 A 类
final class A{
}
//class B extends A{}
class C{
//如果我们要求 hi 不能被子类重写
// 可以使用 final 修饰 hi 方法
public final void hi(){}
}
class D extends C{
//无法重写hi
// @Override
// public void hi(){}
}
//当不希望类的的某个属性的值被修改,可以用 final 修饰
class E{
public final double TAX_RATE = 0.08;//常量
}
//当不希望某个局部变量被修改,可以使用 final 修饰
class F{
public void cry() {
//这时,NUM 也称为 局部常量
final double NUM = 0.01;
//NUM = 0.9;
System.out.println("NUM=" + NUM); }
}
2.Final使用注意事项和细节讨论
-
final修饰得属性又叫常量,一般用XX_XX来命名
-
final修饰的属性在定义时,必须赋初值,并且以后不能在修改,复制可以在如下位置之一
- 定义时:如public final double TAX_RATE = 0.08;//常量
- 在构造器中
- 在代码块中
-
如果final修饰得属性是静态的则初始化的位置只能是
①定义时 ②在静态代码块中
不能在构造器中(静态随类加载,构造器随对象加载)
-
f**inal类不能被继承,**但是可以实例化对象
-
如果类不是final类,但是含有final方法;则该类可以被继承,但是final方法不能被重写
-
final不能修饰**构造方法(**即构造器)
-
final和static往往搭配使用,效率会更高,不会导致类的加载,底层编译器做了优化处理。
-
包装类(Integer,Double,Float,Boolean等等都是final类),String也是final类
final应用实例:
/**
* 请编写一个程序,能够计算圆形的面积。
* 要求圆周率为3.14.赋值的位置3个方式都写一下
*/
public class FinalExercise01 {
public static void main(String[] args) {
Round round = new Round(10);
System.out.println(round.calArea());
}
}
class Round{
private double r;
//定义时赋值
public final static double PI = 3.14;
public final double PI1;
public final double PI2;
//代码块赋值
{
PI1 = 3.14;
}
//构造器赋值
public Round( double r){
this.r = r;
PI2 = 3.14;
}
public double calArea(){
return PI*r*r;
}
public double calArea1(){
return PI1*r*r;
}
}
(七)抽象类
1.抽象类入门和介绍
2.抽象类使用的注意事项和细节讨论
- 抽象类不能被实例化;
-
抽象类不一定包含abstract方法,也就是说,抽象类可以没有抽象abstract方
-
一旦包含了abstract方法,则这个类必须声明为abstract类
-
abstract只能修饰类和方法,不能修饰属性和其他的。
- 抽象类可以有任意成员【抽象类的本质还是类】,比如非抽象方法,构造器、静态属性等等
- 抽象方法不能有主体,即不能实现
- 如果一个类继承了一个抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为abstract类
[外链图片转
- 抽象方法不能使用private、final、static修饰符来修饰,因为这些关键字都是和重写相违背了
- private 私有的,无法重写
- final 最终的,本身就是为了静止修改原来的值
- static 静态的 与重写无关
3.抽象类练习
4. 抽象类最佳实践-模板设计模式
4.1最佳实践
4.2自我总结:
AAA和BBB都继承于Temple这个抽象(abstract)类,Temple有一个job抽象方法。这里AAA需要实现job()方法计算1+…100000的循环时间,然后BBB也需要实现job()方法,也是计算时间,只不过他们的数字不同。他们都需要计算时间,而且计算时间的代码是一样的,这时候我们就把相同代码提取出来,在抽象类Temple写成一个公开的方法calculateTime()用于计算时间,将不相同的代码留在job()方法中,在父类calculateTime()中去调用job()方法给出范围进行时间计算。
当我们有两个类的代码相似时,我们可以同时继承一个抽象类,将相同代码合并成方法写在父类中,不同的代码留在子类同名方法中,当我们new子类对象时就可以直接调用父类的方法使用。
public class TestTemple {
public static void main(String[] args) {
AAA aaa = new AAA();
aaa.job();
// BBB bbb = new BBB();
// bbb.job();
}
}
abstract public class Temple {//抽象类
public abstract void job();//抽象方法
public void calculateTime(){ //实现方法 调用job方法
//得到开始的时间
long start = System.currentTimeMillis();
job();//动态绑定机制
//得到结束的时间
long end = System.currentTimeMillis();
System.out.println("" + (end - start));
}
}
public class AAA extends Temple {
//计算任务
//从1+2+。。。10000;
@Override
public void job(){
long sum = 0;
for (long i = 1; i <=1000000; i++) {
sum +=i;
}
}
}
public class BBB extends Temple{
//计算任务
//从1+2+。。。10000;
@Override
public void job(){
long sum = 0;
for (long i = 1; i <=1000000; i++) {
sum *=i;
}
}
}