您的位置:首页 > 编程语言 > Java开发

Java基础加强重温_01: 基础回顾(类、对象、类成分、封装、构造方法、this关键字)、static关键字(修饰成员变量,成员方法)、继承( )、抽象类(abstract)、模板设计模式

2020-03-25 18:52 309 查看

一、IDAE创建projrct

java:有默认model
Empty project:没有默认model

二、基础回顾

1、什么是类和对象?

类:对同一类事物的抽象(简化、概括…)描述。
对象:类的具体某个实例。 对象==实例

桌子:是一个类 ,这个桌子:是一个对象/实例
猫:是一个类,Tom猫:是一个实例

2、怎么定义类?

public class 类名(首字母大写,遵循驼峰标识) ApplePen

一个java文件可以定义几个类?
无数个class,但是public修饰的类只能有一个,并且与文件名一致。

public class Demo01 {
public static void main(String[] args) {
//0x001
Student student = new Student("乔碧萝殿下",19,"盛世美颜下的直播");

//获取名字
String name = student.getName();
System.out.println(name);
}
}

//java文件中定义多个类
//在教学情况下用的多,实际工作中基本不用,一个类一个文件
class Dog {

}

class Cat {

}

3、类中的成分

public class 类名 {
//1、成员变量(属性、实例变量、类变量...)
//2、成员方法(行为、函数、实例方法、类方法...)
//3、构造方法(构造器、构造函数、解析函数...)

//未来学的
//4、内部类
//5、代码块
}

4、封装

封装是面向对象三大特性之一。(三大特性:抽象、继承、多态)
封装步骤:
1、把成员变量私有化 (使用 private 关键字来修饰成员变量。)
2、提供getter/setter (使用 public 修饰getter和setter方法。)

封装的作用:
1、对于一些私隐可以控制设置和开放
2、可提供代码的逻辑检验(在getter/setter方法中写检验代码)
3、拓展:可以封装方法(组件化)

封装一句话总结:合理隐藏、合理开放

面向对象和面向过程的区别

面向对象/过程:
过程:重头到位实现做饭的过程
1、米(自己去耕田收割)
2、洗米(水龙头怎么接水)
3、煮饭(做电饭煲)
4、盛饭(做碗)

对象:
1、妈妈.public 买米(private 走去市场、private 讨价还价、private 给钱、private 背回来)
2、妈妈.洗米
3、饭煲.做饭
4、自己.盛饭
理解:面向对象即封装方法(或说封装过程),调用方法实现结果,不关注过程,只关注结果

5、构造方法

创建一个学生类,有姓名、年龄、爱好

构造方法的作用:
jvm创建对象,构造方法初始化对象

类名 变量  = new 类名(参数...);

new 类名(参数…), 分两步解析
new: jvm看到new关键字,在堆内存开辟空间,创建对象
类名(参数…): 即构造方法,执行构造方法初始化对象,(无参构造:用系统默认值初始化。有参构造:用传入的参数出初始化)

6、this关键字

this代表所在类的当前对象的引用(地址值),即代表当前对象。

即:构造方法的this,指的是对象本身,谁调用方法this就是谁
1、Student类的对象student调用getNmae()方法

Student student = new Student("乔碧萝殿下",19,"盛世美颜下的直播");
//获取名字,
String name = student.getName();

2、在getName()中,加上this,正常返回(一般getter方法,不用加this。)。这个this就是指对像student(谁调用方法this就是谁

public class Student {
//  创建一个学生类,有姓名、年龄、爱好
private String name;
private int age;
private String hobby;

//默认情况下,系统会赠送一个无参的构造方法
public Student(){

}

//右键->generate->contructor->选中变量->ok
public Student(String name, int age, String hobby) {
this.name = name;
this.age = age;
this.hobby = hobby;
}

public String getName() {
return this.name; //测试加上this。正常返回
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;  //正常getter方法,不用加this。
}
...

this关键字的应用

1、用于普通的gettter与setter方法

2、用于构造器中
构造器即构造方法

三、static关键字

static是静态的意思。 static可以修饰成员变量或者修饰方法。

1、static修饰成员变量 (静态成员变量)

被static修饰的成员是属于类的是放在静态区中,所有的对象【共享】该变量。这个成员变量叫静态成员变量
没有static修饰的成员变量和方法则是属于每个对象的,每个对象都独有的一份。这个成员变量叫实例成员变量

格式:

修饰符 static 数据类型 变量名 = 初始值;

两种成员变量访问对比

静态成员变量的访问

对象.static修饰的成员变量 = xxx;(idea不推荐)
类名.static修饰的成员变量(静态变量) = xxx;

实例变量的访问

对象.实例成员变量

2、static修饰成员方法 (静态成员方法)

有static修饰成员方法,说明这个成员方法是属于类的,这个成员方法称为类方法或者静态方法。
因为类只有一个,所以静态方法在内存区域中也只存在一份,所有的对象都可以共享这个方法。与静态成员变量一样,静态方法也是直接通过类名.方法名称即可访问。

无static修饰的成员方法属于每个对象的, 这个成员方法叫实例方法。
需要注意的是:实例方法是属于每个对象,必须创建类的对象才可以访问。

两种成员变量访问对比

静态成员方法访问

类名.方法名称

实例成员方法访问

对象.实例方法

3、小结:

1.当 static 修饰成员变量或者成员方法时,该变量称为静态变量,该方法称为静态方法。该类的每个对象都共享同一个类的静态变量和静态方法。任何对象都可以更改该静态变量的值或者访问静态方法。但是不推荐这种方式去访
问。因为静态变量或者静态方法直接通过类名访问即可,完全没有必要用对象去访问。

2.无static修饰的成员变量或者成员方法,称为实例变量,实例方法,实例变量和实例方法必须创建类的对象,然后通过对象来访问。

3.static修饰的成员属于类,会存储在静态区,是随着类的加载而加载的,且只加载一次,所以只有一份,节省内
存。存储于一块固定的内存区域(静态区),所以,可以直接被类名调用。它优先于对象存在,所以,可以被所有对象共享。

4.无static修饰的成员,是属于对象,对象有多少个,他们就会出现多少份。所以必须由对象调用

四、继承

就是子类继承父类的属性和行为,使得子类对象可以直接具有与父类相同的属性、相同的行为。子类可以直接
访问父类中的非私有的属性和行为。

理解:继承后,父类中的成员变量和成员方法也有,在子类中不写出来,访问时可以当写出来访问。

继承好处:

  1. 子类会拥有父类的属性和行为,提高代码的复用性(减少代码冗余,相同代码重复利用)。
  2. 使类与类之间产生了关系,共同的代码都写在了父类,只需要修改父类就可以应用所有子类,提高代码拓展性。

1、继承的格式

通过 extends 关键字,可以声明一个子类继承另外一个父类

class 父类 {
...
}

class 子类 extends 父类 {
...
}

特点:

1、Java是单继承的,一个类只能继承一个直接父类。

// 一个类只能有一个父类,不可以有多个父类。
class A {}
class B {}
class C extends A {} // ok
// class C extends A, B {} // error

2、一个类可以有多个子类。

// A可以有多个子类
class A {}
class C1 extends A {}
class C2 extends  A {}

3、可以多层继承。

class A {}

class B extends A {}

class C extends B {}

Object类是所有类的父类: 顶层父类是Object类。所有的类默认继承Object,作为父类。

继承练习案例

请使用继承定义以下类:

  1. 学生类 属性:姓名,年龄 行为:吃饭,睡觉
  2. 老师类 属性:姓名,年龄,薪水 行为:吃饭,睡觉,教书
  3. 班主任 属性:姓名,年龄,薪水 行为:吃饭,睡觉,管理

案例分析
老师类,学生类,还有班主任类,实际上都是属于人类的,我们可以定义一个人类,把他们相同的属性和行为都定义。在人类中,然后继承人类即可,子类特有的属性和行为就定义在子类中了。

代码实现:

父类Human类

public class Human {
// 合理隐藏
private String name ;
private int 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;
}
}

子类Teacher类

public class Teacher extends Human {
// 工资
private double salary ;

// 特有方法
public void teach(){
System.out.println("老师在认真教技术!");
}

public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}

子类Student类

public class Student extends Human{
}

子类BanZhuren类

public class Teacher extends Human {
// 工资
private double salary ;

// 特有方法
public void admin(){
System.out.println("班主任强调纪律问题!");
}

public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}

测试类

public class Test {
public static void main(String[] args) {
Teacher dlei = new Teacher();
dlei.setName("播仔");
dlei.setAge("31");
dlei.setSalary(1000.99);
System.out.println(dlei.getName());
System.out.println(dlei.getAge());
System.out.println(dlei.getSalary());
dlei.teach();

BanZhuRen linTao = new BanZhuRen();
linTao.setName("灵涛");
linTao.setAge("28");     linTao.setSalary(1000.99);
System.out.println(linTao.getName());
System.out.println(linTao.getAge());
System.out.println(linTao.getSalary());
linTao.admin();
Student xugan = new Student();
xugan.setName("播仔");
xugan.setAge("31");
//xugan.setSalary(1000.99); // xugan没有薪水属性,报错!
System.out.println(xugan.getName());
System.out.println(xugan.getAge());
}
}

2、子类不能继承的内容

1、父类private的属性和行为无法被子类【使用】,父类私有的属性和行为被子类继承(储存)

子类可以继承父类的私有成员(成员变量,方法),只是子类无法直接访问而已。
父类的private成员变量,子类可以通过getter/setter方法访问。

2、构造方法:子类不能继承父类的构造器,因为子类有自己的构造器。因为构造方法必须与类名一致,父类的不可能与子类一致,所以不能被继承

拓展:
3、父类静态的方法和变量也可以被继承

3、 继承后构造器的特点,this和super引用构造方法:this()和super()

当类之间产生了关系,其中各类中的构造器,又产生了哪些影响呢? 首先我们要回忆两个事情,构造器的定义格式和作用。

  1. 构造器的名字是与类名一致的。所以子类是无法继承父类构造方法的。
  2. 构造器的作用是初始化对象成员变量数据的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个 super() ,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。(先有爸爸,才能有儿子)继承后子类构造器特点:子类所有构造器的第一行都会先调用父类的无参构造器,再执行自己

super()

每个子类构造方法默认都隐藏了一句话:super(),该方法指的是父类的构造方法

public class Person {
...
}
public class Student extends Person{
...
public Student(){
//  super();  //父类的构造方法
System.out.println("儿子的构造方法");
}
...
}

当一个子类对象被创建的时候,首先会在内存中创建一个父类对象,然后在父类对象的外部放上子类独有的属性,这个两者结合起来形成了一个子类的对象。子类是拥有父类的私有属性和方法,但无法直接使用。
super()调用的时父类无参构造方法,super(参数…) 输入参数后调用的是父类有参构造方法

运行原理

父类空间优先于子类对象产生
在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空
间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。代码体现在子类的构造器调用时,一定先调用父类的构造器。

this()

this()指的是子类的构造方法,可以理解为本类的构造方法
在子类有参构造方法调用子类无参构造,在new子类对象时执行有参构造和无参构造

public class Student extends Person{
...
public Student(){
System.out.println("儿子的构造方法");
}

public Student(String name,int age){
this(); //添加this()
System.out.println("儿子的构造方法");
}
...
}

注意

1、this()与super(): this(),super()必须要放在第一句

  • 对于父类非私有的变量,super存在的价值是:解决子类无法通过this/super直接访问父类的私有变量,设计者为了统一,父类的变量初始化统一放到了父类构造方法中
  • super()为什么要放第一句:如果不是第一句意味着可以this/super去调用父类的变量,而这个时候父类的变量还没初始化。

2、this()和super()不能共存,否则编译异常,只能选择其中之一。本质第一句永远都是super(参数…)

小结:

this和super三大作用:调用属性、调用方法、利用this表示当前对象。

//调用属性
this.成员变量  --   本类的
super.成员变量  --   父类的

//调用方法
this.成员方法名() --   本类的
super.成员方法名()  --   父类的

//指代构造方法
super(...) -- 调用父类的构造器,根据参数匹配确认有参/无参
this(...) -- 调用本类的其他构造器,根据参数匹配确认有参/无参
this()与super()使用详解:https://blog.csdn.net/lncsdn_123/article/details/79025525

4、继承后子类成员变量和成员方法的特点

成员变量

1、子类、父类成员变量不重名:正常访问是没有影响

2、子类、父类成员变量重名
子类会优先访问自己对象中的成员变量。此时想访问父类成员变量需要使用super关键字。super代表的是父类对象的引用,this代表的是当前对象的引用。

super.父类成员变量名

成员方法

1、成员方法不重名:访问没有影响
对象调用方法时,会先在子类中查找有没有对应的方法,若子类中存在就会执行子类中的方法,若子类中不存在就会执行父类中相应的方法。

2、成员方法重名:创建子类对象调用该方法的时候,子类对象会优先调用自己的方法。

this和super的区别

this 能获取本类、父类有权限的属性和行为,能用在任意类中
super 只能调用父类的有权限的属性和行为,super只能用在子类中

理解:子类继承父类有权限的属性和行为,这些权限和行为等于子类的权限和行为,在本类用this获取当然可以

5、方法重写

子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也
称为重写或者复写。声明不变,重新实现。

区分:
方法重载: 同一个类中相同方法名,不同参数类型(两同一不同)

继承的情况下:子类定义与父类同名的方法

1、同名同参同返回值:方法重写,不会报错

2、同名同参不同返回值:报错(二义性问题)
二义性:同名同参的方法在一个类中出现了多个

3、同名同返回值不同参:不报错,等于方法重载

理解:子类继承了父类方法,又在子类定义跟父类同名不同返回值的方法,等于一个类定义两个相同名字不同返回值的方法,因此产生二义性,不知道执行哪个。

应用场景:

认为父类的方法不能满足子类使用,可以进行方法重写。

方法重写案例

定义了一个动物类

public class Animal {
public void run(){
System.out.println("动物跑的很快!");
}
public void cry(){
System.out.println("动物都可以叫~~~");
}
}

定义一个猫类,猫认为父类cry()方法不能满足自己的需求

public class Cat extends Animal {
public void cry(){
System.out.println("我们一起学猫叫,喵喵喵!喵的非常好听!");
}
}

测试

public class Test {
public static void main(String[] args) {
// 创建子类对象
Cat ddm = new Cat();
// 调用父类继承而来的方法
ddm.run();
// 调用子类重写的方法
ddm.cry();
}

方法重写注意事项

  1. 方法重写是发生在子父类之间的关系。
  2. 子类方法覆盖父类方法,必须要保证权限大于>=父类权限。
  3. 子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。
  4. 父类private修饰的方法无法被重写
    public > protected > 缺省

@Override重写注解

  • @Override:注解,重写注解校验!
  • 这个注解标记的方法,就说明这个方法必须是重写父类的方法,否则编译阶段报错。
  • 建议重写都加上这个注解,一方面可以提高代码的可读性,一方面可以防止重写出错!
public class Cat extends Animal {
@Override
public void cry(){
System.out.println("我们一起学猫叫,喵喵喵!喵的非常好听!");
}
}

五、抽象类

父类中的方法,被它的子类们重写,子类各自的实现都不尽相同。那么父类的方法声明和方法主体,只有声明还有意义,而方法主体则没有存在的意义了(因为子类对象会调用自己重写的方法)。换句话说,父类可能知道子类应该有哪个功能,但是功能具体怎么实现父类是不清楚的(由子类自己决定),父类完全只需要提供一个没有方法体的方法签名即可,具体实现交给子类自己去实现。

我们把没有方法体的方法称为抽象方法。Java语法规定,包含抽象方法的类就是抽象类。

  • 抽象方法 : 没有方法体的方法。
  • 抽象类: 包含抽象方法的类。

abstract关键字

abstract是抽象的意思,用于修饰方法方法和类。abstract修饰的方法是抽象方法,abstract修饰的类是抽象类。

1、abstract修饰类-抽象类

如果一个类包含抽象方法,那么该类必须是抽象类。注意:抽象类不一定有抽象方法,但是有抽象方法的类必须定义成抽象类。

//抽象类定义格式
abstract class 类名字 {
}

代码举例:

public abstract class Animal {
public abstract void run();}

抽象类存在的意义是为了被子类继承,否则抽象类将毫无意义。抽象类体现的是模板思想,模板就是通用的东西。抽象类已经是具体的实现(抽象类中可以有成员变量和实现方法),而将模板中不能决定的东西定义成抽象方法,让使用模板(继承抽象类的类)的类去重写抽象方法实现需求,这是典型的模板思想。

抽象类和普通类的区别:

  • 1、抽象类能定义抽象方法,普通类不允许定义抽象方法(如果普通类有抽象方法也变成抽象类)
  • 2、抽象类不能创建对象,普通类可以创建对象。
    没有方法体的抽象方法是不能被调用的,而抽象类中可以定义抽象方法,如果可以创建对象,就可以调用没有方法体的抽象方法。

小结:

抽象类的特征总结起来可以说是 有得有失
有得:抽象类得到了拥有抽象方法的能力。
有失:抽象类失去了创建对象的能力。
其他成员(构造器,实例方法,静态方法等)抽象类都是具备的。

2、abstract修饰方法-抽象方法

使用 abstract 关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体。

//抽象方法定义格式
修饰符 abstract 返回值类型 方法名 (参数列表);

代码举例:

public abstract void run();

特点:

  • 1、必须要被子类重写,体现的是约束作用(约束子类必须重写父类全部的抽象方法)
    子类不重写全部的抽象方法?子类如果不全部重写父类的抽象方法,那子类依然是抽象类
  • 2、抽象方法必须在抽象类内

抽象方法与普通方法的区别:
1、普通方法必须要有方法体,抽象必须没有方法体。(没有方法体即没有{})
2、普通方法结尾不需要加;,抽象方法必须结尾加; (理解:把 {}换成;)

//普通方法
public void work() {
}

//抽象方法
public void work();

定义抽象方法不能和哪些关键字共存:

- 1、private

私有的方法无法被子类重写,abstract的方法必须要被子类重写才有意义

- 2、static

静态的方法属于当前类,类.静态方法,abstract的方法没有方法体,不能直接调用

- 3、final

final是最终的意思。final修饰的类不能被继承。同理,被修饰的方法也不能进行修改。 一句话概述:final修饰的东西不能被修改,不能被继承。abstract的意义是为了让子类实现方法而存在,而final的意义是不让子类进行修改,它们是处于一个互斥的意义。当二者同时修饰于一种东西(无论是类,还是方法)上,则会报错

3、总结

关于抽象类的使用,以下为语法上要注意的细节,虽然条目较多,但若理解了抽象的本质,无需死记硬背。

  1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
    理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
  2. 抽象类中,可以有构造器,是供子类创建对象时,初始化父类成员使用的。
    理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。
  3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
    理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设
    计。
  4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则子类也必须定义成抽象类,编译无法通过而报错。
    理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意
    义。
  5. 抽象类存在的意义是为了被子类继承,抽象类体现的是模板思想。
    理解:抽象类中已经实现的是模板中确定的成员,抽象类不确定如何实现的定义成抽象方法,交给具体的
    子类去实现。

六、抽象类的应用——模板设计模式

设计模式
java一共有23种设计模式,设计模式其实就是开发的套路。
什么是模板
做月饼 先做一个模子,丢进去的做月饼的材料是能变的。把固定的东西确定下来,变化的东西根据实际情况修改就是模板。

我们现在使用抽象类设计一个模板模式的应用,例如在小学的时候,我们经常写作文,通常都是有模板可以套用的。假如我现在需要定义新司机和老司机类,新司机和老司机都有开车功能,开车的步骤都一样,只是驾驶时的姿势有点不同, 新司机:开门,点火,双手紧握方向盘,刹车,熄火 , 老司机:开门,点火,右手握方向盘左手抽烟,刹车,熄火 。我们可以将固定流程写到父类中,不同的地方就定义成抽象方法,让不同的子类去重写。

代码实现

司机开车的模板类

public abstract class Driver {
public void go() {
System.out.println("开门");
System.out.println("点火");
// 开车姿势不确定?定义为抽象方法
ziShi();
System.out.println("刹车");
System.out.println("熄火");
}
public abstract void ziShi();
}

定义两个使用模板的司机

public class NewDriver extends Driver {
@Override
public void ziShi() {
System.out.println("新司机双手紧握方向盘");
}
}
public class OldDriver extends Driver {
@Override
public void ziShi() {
System.out.println("老司机右手握方向盘左手抽烟...");
}
}

测试类

public class Demo02 {
public static void main(String[] args) {
NewDriver nd = new NewDriver();
nd.go();
OldDriver od = new OldDriver();
od.go();
}
}

运行效果:

  • 点赞
  • 收藏
  • 分享
  • 文章举报
MrWuMC 发布了11 篇原创文章 · 获赞 1 · 访问量 270 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐