day09_包丶static丶继承丶this和super丶抽象类丶模板设计模式丶final

包(Package) 

包的本质就是文件夹

作用:

  • 可以避免类重名:有了包之后,类的全名称就变为:包.类名
  • 分类组织管理众多的类,如果将所有的类文件都放在同一个包下,不利于管理和后期维护,所以,对于不同功能的类文件,可以放在不同的包下进行管理
  • 可以控制某些类型或成员的可见范围。如果某个类型或者成员的权限修饰缺省的话,那么就仅限于本包使用

声明包的语法格式

package 包名;

使用包的规则和规范

  • 必须在源文件的代码首行
  • 一个源文件只能有一个声明包的语句
  • 所有单词都小写,每一个单词之间使用.分割
  • 习惯用公司的域名倒置

如何跨包使用类

前提被使用的类或成员的权限修饰符是>缺省的,即可见的

  • 使用类型的全名称,例如:java.util.Scanner input = new java.util.Scanner(System.in);
  • 使用import 语句之后,代码中使用简名称,import语句告诉编译器到哪里去寻找类。
  • 使用java.lang包下的类,不需要import语句,就直接可以使用简名称
  • import语句必须在package下面,class的上面
  • 当使用两个不同包的同名类时,例如:java.util.Date和java.sql.Date。一个使用全名称,一个使用简名称

static关键字

概述

static是一个静态修饰符关键字,表示静态的意思,可以修饰成员变量和成员方法以及代码块。

static修饰成员变量

static 修饰成员变量时,该变量称为类变量。该类的每个对象都共享同一个类变量的值。任何对象都可以更改该类变量的值,但也可以在不创建该类的对象的情况下对类变量进行操作。定义格式:

  

静态成员变量的访问方式:

代码示例

public class Person {
    // 非静态变量
    String name;// 姓名
    // 静态变量
    static String country;// 国籍

    // 构造方法

    public Person() {
    }

    public Person(String name, String country) {
        this.name = name;
        this.country = country;
    }
}

public class Test {
    public static void main(String[] args) {
        // 创建Person对象
        Person p1 = new Person("张三", "中国");
        System.out.println(p1.name+","+p1.country);// 张三,中国

        System.out.println("=======================");

        // 创建Person对象
        Person p2 = new Person();
        // 没有使用static修饰country
        // System.out.println(p2.name+","+p2.country);// null,null
        // 使用static修饰country
        System.out.println(p2.name+","+p2.country);// null,中国

        System.out.println("=======================");

        System.out.println(Person.country);// 中国
    }
}

static修饰成员方法

概述

  • 被static修饰的方法会变成静态方法,也称为类方法,该静态方法可以使用类名直接调用。

day09_包丶static丶继承丶this和super丶抽象类丶模板设计模式丶final_第1张图片

代码示例

public class Person {
    // 非静态方法
    public void method1(){
        System.out.println("Person method1...");
    }

    // 静态方法
    public static void method2(){
        System.out.println("Person method2...");
    }
}
public class Test {
    public static void main(String[] args) {
        /*
            static修饰成员方法:
                格式:修饰符 static 返回值类型 方法名(形参列表){方法体}
                特点:被static修饰的成员方法叫做静态成员方法
                使用:
                    对象名.静态成员方法名(实参);
                    类名.静态成员方法名(实参); ----->推荐
         */
        Person p = new Person();
        p.method2();

        // 类名.静态成员方法名(实参);
        Person.method2();

    }
}

静态方法调用的注意事项:

  • 静态方法中不能出现this关键字
  • 静态方法中只能直接访问静态成员变量和静态成员方法
  • 静态方法中不能直接访问非静态成员变量和非静态成员方法
  • 非静态方法中可以直接访问一切成员变量和成员方法

以后开发中static的应用

  • 以后的项目中,通常会需要一些“全局变量”或者“全局的工具方法”,这些全局变量和方法,可以单独定义在一个类中,并声明为static(静态)的,可以很方便的通过类名访问

static修饰代码块

  • 在java中,被static修饰的代码块被称作静态代码块。static代码块随着类的加载而加载,而且只执行一次,可以用于成员的初始化,不需要建立对象,直接通过类名调用!当你的项目中有某些成员必须在对象建立前就初始化完毕,那就可以使用静态代码块!
    static {
        System.out.println("静态代码块");
    }

继承

继承是面向对象三大特征之一,可以使得子类具有父类的属性和方法,还可以在子类中重新定义,以及追加属性和方法。多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类中无需再定义这些属性和行为,只需要和抽取出来的类构成某种关系。如图所示:

day09_包丶static丶继承丶this和super丶抽象类丶模板设计模式丶final_第2张图片

多个类可以称为子类,也叫派生类;多个类抽取出来的这个类称为父类超类(superclass)或者基类继承描述的是事物之间的所属关系,这种关系是:is-a 的关系。例如,图中猫属于动物,狗也属于动物。可见,父类更通用,子类更具体。我们通过继承,可以使多种事物之间形成一种关系体系。

继承的好处

  • 我们可以将一些共性的属性,行为抽取到一个父类中,子类只需要继承即可,提供了代码的复用性
  • 提高代码的扩展性
  • 类与类之间产生了关系,是学习多态的前提

继承的格式

通过 extends 关键字,可以声明一个子类继承另外一个父类,定义格式如下:

day09_包丶static丶继承丶this和super丶抽象类丶模板设计模式丶final_第3张图片

代码示例

/*
 * 定义动物类Animal,做为父类
 */
class Animal {
    // 定义name属性
    String name;
    // 定义age属性
    int age;
    // 定义动物的吃东西方法
    public void eat() {
        System.out.println(age + "岁的" + name + "在吃东西");
    }
}

/*
 * 定义猫类Cat 继承 动物类Animal
 */
class Cat extends Animal {
    // 定义一个猫抓老鼠的方法catchMouse
    public void catchMouse() {
        System.out.println("抓老鼠");
    }
}

/*
 * 定义测试类
 */
public class ExtendDemo01 {
    public static void main(String[] args) {
        // 创建一个猫类对象
        Cat cat = new Cat();

        // 为该猫类对象的name属性进行赋值
        cat.name = "Tom";

        // 为该猫类对象的age属性进行赋值
        cat.age = 2;

        // 调用该猫的catchMouse()方法
        cat.catchMouse();

        // 调用该猫继承来的eat()方法
        cat.eat();
    }
}

继承后构造方法的访问规则

  • 构造方法的名字是与类名一致的。 构造方法不能被继承
  • 子类中所有的构造方法默认都会访问父类中无参的构造方法 。子类会继承父类中的数据,可能还会使用父类的数据。所以,子类初始化之前,一定要先完成父类数据的初始化,原因在于,每一个子类构造方法的第一条语句默认都是:super( )

如果父类中没有无参构造方法,只有带参构造方法,该怎么办呢?

  • 通过使用super关键字去显示的调用父类的带参构造方法
  • 子类通过this去调用本类的其他构造方法,本类其他构造方法再通过super去手动调用父类的带参的构造方法 

继承后非私有成员的访问规则

  • 当通过“子类”访问非私有成员时,先在子类中找,如果找到就使用子类的,找不到就继续去“父类”中找。

继承后私有成员的访问规则

  • 父类中的成员,无论是公有(public)还是私有(private),均会被子类继承。
  • 子类虽会继承父类私有(private)的成员,但子类不能对继承的私有成员直接进行访问,可通过继承的下来的非私有方法进行间接访问。如图所示:

day09_包丶static丶继承丶this和super丶抽象类丶模板设计模式丶final_第4张图片

继承的特点

 Java只支持单继承,不支持多继承。

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

Java支持多层继承(继承体系)。

class A{}
class B extends A{}
class C extends B{}

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

子类和父类是一种相对的概念。例如:B类对于A来说是子类,但是对于C类来说是父类

一个父类可以同时拥有多个子类

方法重写

我们说父类的所有方法子类都会继承,但是当某个方法被继承到子类之后,子类觉得父类原来的实现不适合于子类,该怎么办呢?我们可以进行方法重写 (Override)。子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现

class Phone {
    public void sendMessage(){
        System.out.println("发短信");
    }
    public void call(){
        System.out.println("打电话");
    }
    public void showNum(){
        System.out.println("来电显示号码");
    }
}

//智能手机类
class NewPhone extends Phone {

    //重写父类的来电显示号码功能,并增加自己的显示姓名和图片功能
    public void showNum(){
        //调用父类已经存在的功能使用super
        super.showNum();
        //增加自己特有显示姓名和图片功能
        System.out.println("显示来电姓名");
        System.out.println("显示头像");
    }
}

public class ExtendsDemo06 {
    public static void main(String[] args) {
        // 创建子类对象
        NewPhone np = new NewPhone();

        // 调用父类继承而来的方法
        np.call();

        // 调用子类重写的方法
        np.showNum();

    }
}

重写的注意事项

  • 方法重写是发生在子父类之间的关系。
  • 子类方法重写父类方法,返回值类型、方法名和参数列表都要一模一样。
  • 子类方法重写父类方法,必须要保证访问权限大于等于父类权限。访问权限从大到小: public protected (默认) private
  • 子类方法的返回值类型必须【小于等于】父类方法的返回值类型(小于其实就是是它的子类,例如:Student < Person)。如果返回值类型是基本数据类型和void,那么必须是相同
  • 使用@Override注解,检验是否重写成功,重写注解校验!建议重写方法都加上这个注解,一方面可以提高代码的可读性,一方面可以防止重写出错!
  • 静态方法不能被重写丶私有等在子类中不可见的方法不能被重写丶final方法不能被重写  

this和super关键字

  • this:存储的“当前对象”的引用。this可以访问:本类的成员属性、成员方法、构造方法;
  • super:存储的“父类对象”的引用。super可以访问:父类的成员属性、成员方法、构造方法;

this关键字的三种用法

this访问本类成员变量: this.成员变量

public class Student{
    String name = "张三";
    public void show(){
        String name = "李四";
        System.out.println("name = " + name);// 李四
        System.out.println("name = " + this.name);// 张三
    }
}

this访问本类成员方法: this.成员方法名();

public class Student{
    public void show(){
        System.out.println("show方法...");
        this.eat();
    }
    public void eat(){
        System.out.println("eat方法...");
    }
}

this访问本类构造方法: this( )可以在本类的一个构造方法中,调用另一个构造方法

public class Student{
    public Student(){
        System.out.println("空参构造方法...");
    }

    public Student(String name) {
        this();//当使用this()调用另一个构造方法时,此代码必须是此构造方法的第一句有效代码。
        System.out.println("有参构造方法...");
    }
}
public class Demo {
    public static void main(String[] args) {
        Student stu2 = new Student();
    }
}

super关键字的三种用法

  • super访问父类的成员变量: super.父类成员变量名

class Fu{
    int num = 100;
}

class Zi extends Fu{
    int num = 10;

    public void show(){
        int num = 1;
        System.out.println("局部变量num:"+num);// 1
        System.out.println("Zi 类中的num:"+this.num);// 10
        System.out.println("Fu 类中的num:"+super.num);// 100

    }
}

super访问父类的成员方法: super.成员方法名();

class Fu{
    public void method1(){
        System.out.println("Fu method1...");
    }
}

class Zi extends Fu{
    public void show(){
        // 访问父类的method1方法
        super.method1();
    }

    @Override
    public void method1(){
        super.method1();// 调用父类的method1方法
        System.out.println("Zi method1...");
    }
}

super访问父类的构造方法: super( )

 class Fu {
    public Fu() {
        System.out.println("Fu 类的空参构造方法..");
    }

    public Fu(String name, int age) {
        System.out.println("Fu 类的有参构造方法..");
    }
}

 class Zi extends Fu {
    public Zi() {
        super();// 调用父类的空参构造方法
        System.out.println("Zi 类的空参构造方法..");
    }

    public Zi(String name, int age) {
        super(name, age);// 调用父类的有参构造方法
        System.out.println("Zi 类的有参构造方法..");
    }
}

public class Demo {
    public static void main(String[] args) {
        Zi zi = new Zi();
        System.out.println("----------------------");
        Zi z2 = new Zi("刘德华", 17);
    }
}

注意事项

  • super访问成员变量和成员方法: 优先去父类中找,如果有就直接使用,如果没有就去爷爷类中找,如果有,就用,依次类推...
  • 子类的构造方法默认会调用父类的空参构造方法,如果父类中的没有空参构造方法,只定义了有参构造方法,会编译报错
  • 子类构造方法中使用super调用父类的构造方法,是为了在创建子类对象的时候,初始化从父类继承过来的属性
  • 在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。代码体现在子类的构造方法调用时,一定先调用父类的构造方法。
  • this(…)super(…) 必须放在构造方法的第一行有效语句,并且二者不能共存

抽象类 

使用abstract关键字修饰的类就是抽象类。这种类不能被创建对象,它就是用来做父类的,被子类继承的。

语法:

day09_包丶static丶继承丶this和super丶抽象类丶模板设计模式丶final_第5张图片

抽象方法的概述

  • 没有方法体,使用abstract修饰的方法就是抽象方法

语法:

作用: 强制要求子类重写的方法可以定义为抽象方法

代码示例


abstract class Animal {
    // 成员变量
    private String name;
    private int age;
    // 构造方法
    public Animal(){

    }
    public Animal(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 show(){
        System.out.println(name+","+age);
    }

    // 抽象方法 ---
    // 因为所有子类吃东西的方法实现不一样
    public abstract void eat();

}


 class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃骨头...");
    }
}



class Cat extends Animal {

    @Override
    public void eat() {
        System.out.println("猫吃鱼...");
    }
}

public class Test {
    public static void main(String[] args) {
        /*
            抽象方法:
                概述: 使用abstract修饰,并且没有方法体的方法
                格式: 修饰符 abstract 返回值类型 方法名(形参列表);
                抽象方法的使用场景:如果父类中某个方法,所有子类都有不同的实现,那么就可以把该方法定义为抽象方法
                抽象方法的作用: 强制要求子类重写

         */
        Dog d = new Dog();
        d.eat();

        Cat c = new Cat();
        c.eat();
    }
}

抽象类的注意事项

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

  1. 抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。

    理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。

  2. 抽象类中,也有构造方法,是供子类创建对象时,初始化父类成员变量使用的。

    理解:子类的构造方法中,有默认的super()或手动的super(实参列表),需要访问父类构造方法。

  3. 抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。

    理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。

  4. 抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。

    理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。

模板设计模式

  • 设计模式就是解决一些问题时的固定思路,也就是代码设计思路经验的总结。 模板设计模式概述:针对某些情况,在父类中指定一个模板,然后根据具体情况,在子类中灵活的具体实现该模板

抽象类体现的就是模板设计思想

  • 模板是将通用的东西在抽象类中具体的实现,而模板中不能决定的东西定义成抽象方法,让使用模板(继承抽象类的类)的类去重写抽象方法实现需求。

模板模式的实现步骤

  1. 定义抽象父类作为模板
  2. 在父类中定义"模板方法"--- 实现方法(通用模板)+抽象方法(填充模板)
  3. 子类继承父类,重写抽象方法(填充父类的模板)
  4. 测试类中创建子类对象,通过子类调用父类的“实现的方法”+ “子类重写后的方法”

代码示例


// 父类
abstract class Driver {
    // 开车方法 通用模板
    public void driveCar() {
        System.out.println("开门");
        System.out.println("点火");
        // 姿势??
        ziShi();
        System.out.println("刹车");
        System.out.println("熄火");
    }

    // 姿势方法  填充模板
    public abstract void ziShi();
}

//现在定义两个使用模板的司机:

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

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

public class Test {

    public static void main(String[] args) {
        // 创建新司机对象
        NewDriver d1 = new NewDriver();
        d1.driveCar();

        // 创建老司机对象
        OldDriver d2 = new OldDriver();
        d2.driveCar();
    }

}

可以看出,模板模式的优势是,模板已经定义了通用架构,使用者只需要关心自己需要实现的功能即可!非常的强大!

final关键字

概述: final关键字表示不可改变。可以用于修饰类、方法和变量。

修饰类:表示这个类不能被继承,没有子类

查询API发现像 public final class Stringpublic final class Mathpublic final class Scanner 等,很多我们学习过的类,都是被final修饰的,目的就是供我们使用,而不让我们所以改变其内容。

代码示例

final class Eunuch{//太监类
	
}
class Son extends Eunuch{//错误
	
}

修饰方法表示这个方法不能被子类重写

代码示例

class Father{
	public final void method(){
		System.out.println("father");
	}
}
class Son extends Father{
	public void method(){//错误
		System.out.println("son");
	}
}

修饰变量

基本类型的局部变量:被final修饰后,只能赋值一次,不能再更改。代码如下:

public class FinalDemo1 {
    public static void main(String[] args) {
        // final修饰基本数据类型
        final int NUM = 10;
        // NUM = 20;// 编译报错,final修饰的变量只能赋值一次,不能重复赋值
    }
}

引用类型的局部变量:被final修饰后,只能指向一个对象,地址不能再更改。但是不影响对象内部的成员变量值的修改,代码如下:

public class FinalDemo2 {
    public static void main(String[] args) {
        // 引用类型
        final Student stu = new Student("张三", 18);
        //stu = new Student("李四",19);// 编译报错
        stu.setAge(19);
    }
}

成员变量

成员变量涉及到初始化的问题,初始化方式有两种,只能二选一:

显示初始化;

public class FinalVariable { 
    final int NUM1 = 10;
}

构造方法初始化

public class FinalVariable {
    final int NUM2;

    public FinalVariable(int NUM2) {
        this.NUM2 = NUM2;
    }

    public FinalVariable() {
        this.NUM2 = 10;
    }
}

被final修饰的常量名称,一般都有书写规范,所有字母都大写

你可能感兴趣的:(#,一:JavaSE,java)