Java面向对象进阶(二)

Java面向对象进阶(二)

1.什么是包?

○ 包是用来分门别类的管理各种不同类的,类似于文件夹、建包利于程序的管理和维护
○ 建包的语法格式:package 公司域名倒写.技术名称,报名建议全部英文小写,且具意义
○ 建包语句必须在第一行,一般IDEA工具会帮助创建

2.导包

○ 相同包下的类可以直接访问,不同包下的类必须导包,才可以使用!import包名.类名;
○ 假如一个类中需要用到不同类,而这个两个类的名称是一样的,那么默认只能导入一个类,另一个类要带包名访问。

以下是测试类所处包的位置
在这里插入图片描述

定义一个Student类(直属于d1_package包下),测试不同位置下的类调用该类,是否需要导包操作

package com.github.d1_package;

public class Student {
    public void test () {
        System.out.println("ok");
    }
}

在相同包下的不同类Test中,可以直接访问,不需要导包

package com.github.d1_package;

public class Test {
    public static void main(String[] args) {
        Student student = new Student();
        student.test();
    }
}

在不同包下的类Test2中,必须要导包才能使用

package com.github.d1_package.itcast;

import com.github.d1_package.Student;

public class Test2 {
    public static void main(String[] args) {
        Student student = new Student();
        student.test();
    }
}

在itcast包下创建一个同名的Student类

package com.github.d1_package.itcast;

public class Student {
    public void test () {
        System.out.println("导包成功!");
    }
}

在Test类中,导入类名相同,但所处路径不同的包时,默认只能导入一个类,另一个类要带包名访问

package com.github.d1_package;

public class Test {
    public static void main(String[] args) {
        Student student = new Student();
        student.test();
        com.github.d1_package.itcast.Student student1 = new com.github.d1_package.itcast.Student();
        student1.test();
    }
}

权限修饰符

1.什么是权限修饰符?

○ 权限修饰符:是用来控制一个成员变量能够被访问的范围○ 可以修饰成员变量,方法,构造器,内部类,不同权限修饰符的成员能够被访问的范围将受到限制

2.权限修饰符的分类和具体作用范围:

○ 权限修饰符:有四种作用范围由小到大(private->缺省->protected->public)权限修饰符
以下是测试类所处包的位置
这是以下测试类的位置

定义一个Fu类,用方法能否被调用来测试权限修饰符的作用范围

package com.github.d2_modifier;

public class Fu {
    private void privateMethod() {
        System.out.println("private");
    }
    void method () {
        System.out.println("缺省");
    }
    protected void protectedMethod() {
        System.out.println("protected");
    }
    public void publicMethod() {
        System.out.println("public");
    }
}

在Fu类下访问,都能成功访问

public static void main(String[] args) {
        Fu fu = new Fu();
        fu.privateMethod();
        fu.method();
        fu.protectedMethod();
        fu.publicMethod();
    }

在同一个包下的不同类Test中,private修饰的方法不能被调用

package com.github.d2_modifier;

public class Test {
    public static void main(String[] args) {
        Fu fu = new Fu();
        // fu.privateMethod();  报错
        fu.method();
        fu.protectedMethod();
        fu.publicMethod();
    }
}

在不同包下的子类Zi中,private、缺省修饰的方法不能被调用
注意:protected要求的是不同包下的子类,需要通过子类来访问

package com.github.d2_modifier.itcast;

import com.github.d2_modifier.Fu;

public class Zi extends Fu{
    public static void main(String[] args) {
        Fu fu = new Fu();
        // fu.privateMethod(); 报错
        // fu.method(); 报错
        // fu.protectedMethod(); 报错
        // 报错原因:protected要求的是不同包下的子类,需要通过子类来调用!
        fu.publicMethod();
        
        Zi zi = new Zi();
        // zi.privateMethod(); 报错
        // zi.method(); 报错
        zi.protectedMethod();
        zi.publicMethod();
    }
}

在不同包下的其他类Test2中,private、缺省、protected修饰的方法不能被调用

package com.github.d2_modifier.itcast;

import com.github.d2_modifier.Fu;

public class Test2 {
    public static void main(String[] args) {
        Fu fu = new Fu();
        // fu.privateMethod(); 报错
        // fu.method(); 报错
        // fu.protectedMethod(); 报错
        fu.publicMethod();
    }
}

final

1.final的作用

○ final 关键字是最终的意思,可以修饰(类、方法、变量)

○ 修饰类:表明该类是最终类,不能被继承

public final class People {

}
class Student extends People{

}  // 报错:无法从final 'com.github.d3_final.People' 继承

○ 修饰方法:表明该方法是最终方法,不能被重写

public class People {
    public final void speak (){
        System.out.println("人会说话");
    }
}

class student extends People {
    @Override
    public void speak() {
        System.out.println("学生会说话");
        // 报错:'speak()' 无法重写 'com.github.d3_final.People' 中的 'speak()';重写的方法为 final
    }
}

○ 修饰变量:表示该变量第一次赋值后,不能再次被赋值(有且仅能被赋值一次,相当于常量)

public class Test2 {
	// 必须要进行赋值,否则会报错
    public static final int onlineNumber = 125;

    private final String name = "猪八戒";

    public static void main(String[] args) {
        // 1.修饰局部变量
        final double pai = 3.14;
        // pai = 5.12;
        // 报错:无法将值赋给 final 变量 'pai'

        // 2.修饰全局变量
        // 2.1 修饰静态成员变量
        // onlineNumber = 112;
        // 报错:无法将值赋给 final 变量 'onlineNumber'

        // 2.2 修饰实例成员变量
        Test2 test2 = new Test2();
        // test2.name = "天蓬元帅";
        // 报错:无法将值赋给 final 变量 'name'
    }
}

2.final修饰变量的注意事项

○ final修饰的变量是基本类型:那么变量存储的数据值不发生改变
○ final修饰的变量是引用类型:那么变量存储的地址值不能发生改变,但是地址指向的对象内容是可以发生改变的

public class Teacher {
    private String name;

    public Teacher() {
    }

    public Teacher(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
class Test3 {
    public static void main(String[] args) {
        final Teacher teacher = new Teacher("张三");
        // teacher = null;
        // 报错:无法将值赋给 final 变量 'teacher'
        System.out.println(teacher.getName()); // 张三
        teacher.setName("李四");
        System.out.println(teacher.getName()); // 李四
        // 地址指向的对象内容发生改变
    }
}

常量

1.常量

○ 常量是使用了public static final修饰的成员变量,必须有初始化值,而且执行的过程中其值不能被改变
○ 常量名的命名规范;英语单词全部大写,多个单词下划线连接起来
○ 常量的作用:通常用来记录系统的配置数据

public class Test {
    public static final String LOGIN_NAME = "admin";
    public static final String PASSWORD = "123456";
}

2.常量做信息配置的原理、优势

○ 在编译阶段会进行“宏替换”:把使用常量的地方全部替换成真实的字面量
○ 维护系统容易,可读性更好

3.选择常量做信息标志和分类:

○ 代码可读性好,实现了软编码形式

枚举

1.枚举的概述

○ 枚举是Java中的一种特殊类型
枚举的作用:“是为了做信息的标志和信息的分类”

2.定义枚举类的格式:

enum

3.枚举的声明方式:

一、类外声明:

enum Color {
    RED,GREEN,BLUE;
}

public class Test {
    public static void main(String[] args) {
        Color color = Color.BLUE;
        System.out.println(color);  // BLUE
    }
}

二、内部类中声明

public class Test2 {
    enum Color {
        RED,GREEN,BLUE;
    }

    public static void main(String[] args) {
        Color color = Color.BLUE;
        System.out.println(color);  // BLUE
    }
}

4.枚举的特征:

○ 枚举类都是继承了类型:java.lang.Enum
enum
○ 枚举都是最终类,不可以被继承

public class Test3 extends Color{  //报错: 无法从enum 'com.github.d5_enum.Color' 继承
    
}

○ 构造器都是私有的,枚举对外不能创建对象

public class Test3{  
    // Color color = new Color(); // 报错:无法实例化枚举类型
}

从枚举enum的反编码中可以看出,构造器被私有化,不能创建对象

enum Color {
    RED,
    GREEN,
    BLUE;

    private Color() {
    }
}

○ 枚举类相当于是多例模式

5.枚举的内置方法

○ values() 返回枚举类中所有的值,返回类型是数组,用于迭代枚举元素

public class Test4 {
    public static void main(String[] args) {
        for (Color myVar : Color.values()){  
            // Color.values()返回一个包含所有枚举值的数组
            // myVar 用于接收每一个枚举值
            System.out.print(myVar + "\t");  // RED	GREED BLUE
        }
    }
}

○ ordinal()方法可以找到每个枚举常量的索引,就像数组索引一样。

public class Test5 {
    public static void main(String[] args) {
        Color[] arr = Color.values();

        //迭代枚举
        for (Color color : arr){
            // 获取索引
            System.out.println(color + " at index " + color.ordinal());
        }
    }
}

○ valueOf()方法返回指定字符串值的枚举常量

public class Test6 {
    public static void main(String[] args) {
        System.out.println(Color.valueOf("GREEN"));
        // System.out.println(Color.valueOf("green"));
        // 枚举类中不存在green会报错 报错:IllegalArgumentException: No enum constant com.github.d5_enum.Color.green
    }
}

6.枚举类成员

枚举类跟普通类一样可以用自己的变量、方法和构造函数,构造函数只能使用 private 访问修饰符,所有外部无法调用。枚举既可以包含具体方法,也可以包含抽象方法,如果枚举类具有抽象方法,则枚举类的每个实例都必须实现它。

public class Test7 {
    enum Season {
        SPRING,SUMMER,AUTUMN,WINTER;

        // 构造函数
        private Season(){
            System.out.println("The season is " + this.toString());
        }
        public void seasonInfo() {
            System.out.println("Universal Season");
        }
    }
    public static void main(String[] args) {
        Season season = Season.AUTUMN;
        // The season is SPRING
        // The season is SUMMER
        // The season is AUTUMN
        // The season is WINTER
        System.out.println(season);
        // AUTUMN
        season.seasonInfo();
        // Universal Season
    }
}

抽象类

1.抽象类的概述

○ 在 Java 中abstract是抽象的意思,可以修饰类、成员方法
abstract修饰类,这个类就是抽象类;修饰方法,这个方法就是抽象方法

2.定义抽象类、抽象方法的格式:

abstract
注意事项:
○ 抽象方法只有方法签名,不能声明方法体
○ 一个类中如果定义了抽象方法,这个类必须声明成抽象类,否则报错

3.抽象的使用场景

○ 抽象类可以理解成不完整的设计图,一般作为父类,让子类来继承
○ 当父类知道子类一定要完成某些行为,但是每个子类该行为的实现又不同,于是该父类就把该行为定义成抽象方法的形式,具体实现交给子类去完成,此时这个类就可以声明成抽象类

定义父类Animal并将其变成抽象类

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

定义子类Dog,重写抽象方法,不重写会报错

public class Dog extends Animal{

    @Override
    public void run() {
        System.out.println("狗在跑~");
    }
}```
定义测试类Test,完成测试
```java
public class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.run();  // 狗在跑~
    }
}

注意事项:
一个类如果继承了抽象类,那么这个类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类

public abstract class Cat extends Animal{
    // 不报错
}

4.抽象类的特征和注意事项

○ 类有的成员(成员变量、方法、构造器)抽象类都具备
○ 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
○ 一个类继承了抽象类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类
○ 不能用abstract修饰变量、代码块、构造器
最重要的特征:得到了抽象方法,失去了创建对象的能力(有得有失

public class Test2 {
    Animal animal = new Animal();  // 报错: 'Animal' 为 abstract;无法实例化
}

原因;
一、抽象方法中没有方法体,创建的实例对象调用抽象方法就会报错
二、尽管抽象类中不定义抽象方法,但出于程序的严谨性,也会报错

5.抽象类的应用知识:模版方法模式

应用场景:当系统中出现同一个功能多出开发,而该功能中大部分代码是一样的,只有其中部分可能不同的使用
模版方法模式实现步骤(写作文)
○ 1.定义一个抽象类

public abstract class Write {
    
}

○ 2.定义2个方法,一个是模版方法:把相同代码放里面去,不同代码定义成抽象方法

public abstract class Write {
    // 定义一个模版方法
    public final void write() { 
    	// 模版方法是给子类直接使用的,不是让子类重写的,一旦子类重写了模版方法,则模版方法就失效了,因此,加上final后可以防止子类重写了模版方法,这样更安全、专业
        System.out.println("请以《我最熟悉的人为题》:");
        System.out.println("\t\t\t\t《我最熟悉的人》");
        System.out.println("我最熟悉的人是:");

        // 正文部分
        System.out.println(writeMain());

        System.out.println("这就是我最熟悉的人。");
    }

    // 定义一个抽象方法
    public abstract String writeMain();
}

○ 3.子类继承抽象类,重写方法或创建对象时重写方法

public class Test3{
    public static void main(String[] args) {
        Write write = new Write() {
            @Override
            public String writeMain() {
                return "他总是无微不至地照顾我……";
            }
        };
        write.write();
        /*
        请以《我最熟悉的人为题》:
				《我最熟悉的人》
        我最熟悉的人是:
        他总是无微不至地照顾我……
        这就是我最熟悉的人。
         */
    }
}

接口

1.接口的定义与特点

○ 接口的格式如下
interface
○ JDK8之前接口只能是抽象方法和常量,没有其他成分
○ 接口不能实例化
○ 接口中的成员都是public修饰的,写不写都是,因为规范的目的是为了公开化

public interface InterfaceDemo {
    // 1.常量
    String LOGIN_NAME = "admin";
    // public static final String LOGIN_NAME = "admin";

    // 2.抽象方法
    void run();
    // public abstract void run();
}

2.接口的用法:

○ 接口是用来被类实现(implement)的,实现接口的类称为实现类。实现类可以理解成所谓的子类
在这里插入图片描述
○ 从上面可以看出,接口可以被类单实现,也可以被类多实现

3.接口实现的注意事项

○ 一个类实现接口,必须重写完全部接口的全部抽象方法,否则这个类需要定义成抽象类

4.接口和接口的关系

多继承,一个接口可以同时继承多个接口
定义三个接口

public interface People {
    void eat();
    void speak();
}
public interface Law {
    void rule();
}

接口SportMan用于继承接口People,Law,实现接口的合并

public interface SportMan extends People, Law{
    void run();
}

最后实现类BasketballMan只需要连接SportMan接口就可以实现三个接口,这就是接口的多继承

public class BasketballMan implements SportMan {

    @Override
    public void rule() {

    }

    @Override
    public void eat() {

    }

    @Override
    public void speak() {

    }

    @Override
    public void run() {

    }
}

5.接口多继承的作用

○ 规范合并,整合多个接口为一个接口,便于子类实现

6.jdk8开始接口新增方法

1.第一种:默认方法
○ 类似之前写的普通实例方法,但必须用default修饰
○ 默认会public修饰,需要用接口的实现类的对象来调用

public interface Default {
    default void run() {
        System.out.println("跑~");
    }
}
class Animal implements Default{}
class Test{
    public static void main(String[] args) {
        Animal animal = new Animal();
        animal.run();
        // Default.run();  // 报错
        // Animal.run(); // 报错
    }
}

2.第二种:静态方法
○ 默认会public修饰,必须static修饰
注意:接口的静态方法必须用本身的接口名来调用

public interface Static {
    static void run(){
        System.out.println("跑~");
    }
}
class Animal2 implements Static{ }
class Test2 {
    public static void main(String[] args) {
        Static.run();
        Animal2 animal2 = new Animal2();
        // animal2.run(); // 报错
        // Animal.run(); // 报错
    }
}

3.第三种:私有方法
○ 就是私有的实例方法,必须使用private修饰,从JDK1.9开始有
○ 只能在本类中被其他的默认方法或者私有方法访问

public interface Private {
    private void run() {
        System.out.println("跑~");
    }
    default void speak() {
        // 可以在默认方法内调用
        run();
        look();
        System.out.println("说~");
    }
    static void hear() {
        // run();  // 报错
        System.out.println("听~");
    }
    private void look() {
        run();
        System.out.println("看~");
    }
}
class Animal3 implements Private{}
class Test3 {
    public static void main(String[] args) {
        // Private.run(); // 报错
        // Animal3.run(); // 报错
        Animal3 animal3 = new Animal3();
        // animal3.run(); // 报错
        animal3.speak(); //跑~  跑~  看~  说~

    }
}

接口的注意事项

○ 1.接口不能创建对象
○ 2.一个类实现多个接口,多个接口中有同样的静态方法不冲突

interface AA {
    static void run(){
        System.out.println("AA");
    }
}
interface BB {
    static void run() {
        System.out.println("BB");
    }
}
class CC implements AA,BB {

}
public class Test1 {
    public static void main(String[] args) {
        CC cc = new CC();
        // cc.run(); // 报错,接口的静态方法必须用本身的接口名调用
        AA.run(); // AA
        BB.run(); // BB
    }
}


○ 3.一个类继承了父类,同时又实现了接口,父类中和接口有同名方法,默认用父类的

interface Dog{
    default void run() {
        System.out.println("狗跑~");
    }
}
class Animal {
    public void run(){
        System.out.println("动物跑~");
    }
}
public class Test2 extends Animal implements Dog{
    public static void main(String[] args) {
        Test2 test2 = new Test2();
        test2.run();  // 动物跑~
    }
}

○ 4.一个类实现了多个接口,多个接口中存在同名的默认方法,不冲突,这个类重写该方法即可

interface Cat{
    default void run(){
        System.out.println("猫跑~");
    }
}
interface Lion{
    default void run(){
        System.out.println("狮子跑~");
    }
}
class Animal2 implements Cat,Lion{

    @Override
    public void run() {
        System.out.println("动物跑~");
    }
}
public class Test3 {
    public static void main(String[] args) {
        Animal2 animal2 = new Animal2();
        animal2.run();  // 动物跑~
    }
}

○ 5.一个接口继承多个接口,是没问题的,如果多个接口中存在规范冲突则不能多继承

interface AAA {
    void run();
}
interface BBB {
    // int run(); // 与AAA中的run方法规则犯冲突 报错
    void run();
}
interface CCC extends AAA,BBB{
    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值