final关键字、访问修饰符、内部类

目录

一、final关键字

1.1 概述

1.2使用方式

1.3 修饰方法 

1.4  修饰变量-局部变量

 二、访问修饰符

2.1 概述

2.2 不同权限的访问能力

三、内部类

1.1 概述

1.2 匿名内部类[重点]


一、final关键字

1.1 概述

学习了继承后,我们知道,子类可以在父类的基础上改写父类内容,比如,方法重写。那么我们能不能随意的继承API中提供的类,改写其内容呢? 显然这是不合适的。为了避免这种随意改写的情况。

Java提供了 final 关键字用于修饰不可改变内容。

 final: 不可改变。可以用于修饰类、方法和变量。
类:被修饰的类,不能被继承。
方法:被修饰的方法,不能被重写。
变量:被修饰的变量,不能被重新赋值。

1.2使用方式

修饰类

格式如下:

final class 类名{

}

 代码:

final class Fu {
}
// class Zi extends Fu {} // 报错,不能继承final的类

1.3 修饰方法 

格式如下:

修饰符 final 返回值类型 方法名(参数列表){

                //方法体

}

public class Test01 {
    public static void main(String[] args) {
        final int a = 5;//final修饰变量,变量一旦赋值后不允许修改它的值(常量)


    }
}

1.4  修饰变量-局部变量

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

public static void main(String[] args) {
        // 声明变量,使用final修饰
        final int a;
        // 第一次赋值 
        a = 10;
        // 第二次赋值
        a = 20; // 报错,不可重新赋值

        // 声明变量,直接赋值,使用final修饰
        final int b = 10;
        // 第二次赋值
        b = 20; // 报错,不可重新赋值
    }

1.5 修饰变量-成员变量

成员变量涉及到初始化的问题,初始化方式有显示初始化和构造方法初始化,只能选择其中一个:

  • 显示初始化(在定义成员变量的时候立马赋值)(常用);

  • public class Student {
        final int num = 10;
    }

  • 构造方法初始化(在构造方法中赋值一次)(不常用,了解即可)。

 注意:每个构造方法中都要赋值一次

public class Student {
    final int num = 10;
    final int num2;

    public Student() {
        this.num2 = 20;
//     this.num2 = 20;
    }
    
     public Student(String name) {
        this.num2 = 20;
//     this.num2 = 20;
    }
}

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

 二、访问修饰符

2.1 概述

在lava中提供了四种访问权限,使用不同的访问权限修饰符修饰时,被修饰的内容会有不同的访问权限。
        public: 公共的    所修饰的类、变量、方法,在内外包均具有访问权限;
        protected: 受保护的     这种权限是为继承而设计的,protected所修饰的成员,对所有子类是可访问的,单只对同包的类是可访问的,对外包的非子类是不可以访问;
        default: 默认的     只对同包的类具有访问的权限,外包的所有类都不能访问;
        private:私有的     私有的权限,只对本类的方法可以使用;

2.2 不同权限的访问能力

可见,public具有最大权限。private则是最小权限。

编写代码时,如果没有特殊的考虑,建议这样使用权限:

        成员变量使用 private ,隐藏细节。
        构造方法使用 public,方便创建对象。
        成员方法使用 public,方便调用方法。

小贴士: 不加权限修饰符,其访问能力与default修饰符相同

//同一类中都可以访问

public class Person {
    public String name;
    protected int age;
    String sex;
    private String addr;

    public void fun(){
        name="zy";
        age=19;
        sex="女";
        addr="光山";
    }
}


//同一包中 子类

public class Student extends Person{
    public void fun(){
        this.name="zs";
        this.age=18;
        this.sex="男";
    }
}

//同一包中 无关类

public class Test01 {
    public static void main(String[] args) {

        Person p = new Person();
        p.name="zy";
        p.age=20;
        p.sex="女";



    }
}


//不同包的子类

public class Teacher extends Person {
    public void fun(){
        this.name="za";
        this.age=20;
    }
}



//不同包中的无关类

public class Test01 {
    public static void main(String[] args) {
        Person p = new Person();
        p.name="dxx";
    }
}


三、内部类

3.1 概述

什么是内部类

将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类

成员内部类

        成员内部类:定义在类中方法外的类。

定义格式:

class 外部类{
       class 内部类{

        }

}

访问特点

        内部类可以直接访问外部类的成员,包括私有成员。

        外部类要访问内部类的成员,必须要建立内部类的对象。

创建内部类对象格式:

外部类名.内部类名 对象名  new 外部类型().new 内部类型();

3.2 匿名内部类[重点]

        匿名内部类:是内部类的简化写法。它的本质是一个 带具体实现的 父类或者父接口的 匿名的 子类对象。开发中,最常用到的内部类就是匿名内部类了。以接口举例,当你使用一个接口时,似乎得做如下几步操作
        1.定义子类
        2.重写接口中的方法
        3.创建子类对象
        4.调用重写后的方法

我们的目的,最终只是为了调用方法,那么能不能简化一下,把以上四步合成一步呢? 匿名内部类就是做这样的快捷方式。

前提

匿名内部类必须继承一个父类或者实现一个父接口 。

格式

new 父类名或者接口名(){
        //方法重写
        @Override
        public void method() {
                // 执行语句

        }

}

使用方式 

public abstract class Person {
    public  void say(){
        System.out.println("学生在读书");
    }
}


public class Student extends Person{
    public void say(){
        System.out.println("学生在读书");
    }
}



public abstract interface USB {
    public abstract void read();
}



public class Kingston implements USB{
    @Override
    public void read() {
        System.out.println("金士顿完成读操作");
    }
}




public class Test01 {
    public static void main(String[] args) {
        Person p = new Student();//实例化Person的子类Student对象


        //匿名内部类: 它的本质是一个 带具体实现的 父类或者父接口的 匿名的 子类对象;
        //如果抽象类或者接口的抽象方法没办法具体定义实现,或者需要根据具体情况具体实现,此时没办法定义子类,可以使用匿名类
       Person person = new Person() {
           @Override
           public void say() {
               System.out.println("匿名内部类实现抽象方法say");
           }
       };

       //匿名内部类:直接创建子类对象 重写方法 然后调用
       USB usb = new USB() {
           @Override
           public void read() {
               System.out.println("金士顿读操作");
           }
       };
       usb.read();

       //定义子类 实现方法 创建子类对象 调用方法
       USB usb1 = new Kingston();
       usb1.read();
    }

}

public class User {
    public static void main(String[] args) {
        /**
         * 基本数据类型和引用类型作为参数的区别:
         *  1.基本数据类型作为参数,修改的是剧本,不会更改本身;
         *  2.引用数据类型作为参数,修改的是本身;
         */

        int a = 10;
        System.out.println("改变前a的值:" + a); //10
        change(a);
        System.out.println("改变后a的值:" + a);  //10

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

        int[] arr=new int[3];
        arr[0]=10;
        System.out.println("改变前arr数组第一个元素的值:" + arr[0]);//10
        change(arr);
        System.out.println("改变后arr数组第一个元素的值:" + arr[0]);//50
    }
    public static void change(int a){
        a=50;
    }

    public static void change(int[] arr){
        arr[0]=50;
    }
}

 

猜你喜欢

转载自blog.csdn.net/weixin_67224308/article/details/127978443