简述Java权限、内部类、final关键字

本人小白一枚,欢迎大家一起讨论学习,如有错误,还望大家指教。

final:代表最终的、不可改变的。既可修饰类、方法、变量(局部变量、成员变量)。

  • 被final修饰的类不能被继承。
  • 被final修饰的方法不能被重写。
  • 被final修饰的变量,不能被重新赋值。

当修饰变量时
1、局部变量–基本类型
基本类型的局部变量,被final修饰后,只能赋值一次,不能再更改。

public static void main(String[] args) {
        // 以下两种赋值方式都可以
        final int num1;
        num1 = 10;
        final int num2 = 10;
   }

2、局部变量–引用类型
引用类型的局部变量,被final修饰后,只能指向一个对象,地址不能更改,但是可以改变对象的成员变量的值。

public void static main(String[] args) {
   final User user = new User();
   // 创建一个新的对象,赋值给user,无法通过编译
   user = new User();
   // 可以通过SET方法修改对象的属性
   user.setName("张三");
}

3、成员变量
对于成员变量来说,如果使用final关键字修饰,那么这个变量同样无法改变,如同常量一般。
但因为成员变量具有默认值,所以使用final之后必须手动赋值,不会再给默认值了。
成员变量初始化的方式有两种:只能二选一:

  • 显示初始化:final String name = "灰太狼";
  • 构造函数初始化:
private final String name;

public Person() {
    name = "喜洋洋";
}

在这里插入图片描述
注意:上面我们已经提到了,因为成员变量具有默认值,所以我们必须在使用上面的显示初始化或者构造函数初始化,不能像修饰局部变量时,那样赋值。
被final修饰的常量名称,书写规范就是所有字母都用大写
权限修饰符
Java中提供了四种访问权限,使用不同的访问权限修饰时,被修饰的内容会有不同的访问权限。

  • public:共有的
  • protected:受保护的
  • default:默认的
  • private:稀有的

注意:default并不是关键字。
在这里插入图片描述
内部类
将一个类定义在另一类里,对里面的类就称为内部类(内置类、嵌套类)。
定义格式:

修饰符 class 外部类名 {
    修饰符 class 内部类名 {
        //....
    }
    //....
}

为什么要定义内部类?
类是对我们现实生活中事物的描述,当我们描述事物时,若一个事物内部还包含其他事物,就可以定义内部类。例如,人体类包含心脏类。
内部类分类:
1、成员内部类:定义在类中方法外的类。
2、局部内部类(包含匿名内部类)
访问特点:(不作为重点掌握,但必须了解,可能为面试题)
1、内部类可以直接访问外部类中的成员,包括私有成员。之所以可以直接访问类中的成员,是因为内部类中持有一个外部类的引用,格式:外部类名.this。
2、外部类要访问内部类,必须建立内部类的对象。
访问格式:
当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中,直接建立内部类的对象。
格式:外部类名.内部类名 变量名 = 外部类对象.内部类对象;
Outer.Inner inner = new Outer().new Inner();
注意:内部类仍然是一个独立的类,在编译之后会内部类会被编译成独立的.class文件,但是前面冠以外部类的类名 和$符号 。比如,Person$Heart.class,所以在我们给类取名时,建议不要使用$符号。
在这里我们总结下上述中提到的问题:

  • 编译后产生的.class文件个数:有多少类,就产生多少.class文件。
  • 产生.class文件名的规律:外部类名 + $ + 内部类名 + .class
  • 匿名内部类:外部类名 + $ + 数字 + .class。例如:ClassE$1$1.class
class Outside {
    private String name = "刘德华";
    
    class Inside {
        private String name = "周星驰";
        public void method() {
            System.out.println(name);
        }
        class Ininside {
            private String name = "周润发";
            public void method() {
                System.out.println(Outside.this.name);
            }
            class Inininside {
                private String name = "周华健";
                public void method() {
                    System.out.println(name);
                }
                class $ {
                    private String name = "$";
                    public void method() {
                        System.out.println(name);
                    }
                }
            }
        }
    }
}
public class InsideClassDemo {
    public static void main(String[] args) {
        Outside.Inside.Ininside.Inininside demo = new Outside().new Inside().new Ininside().new Inininside();
        demo.method();
    }
}

编译后产生的class文件
在这里插入图片描述

public class InsideClassDemo2 {
}

class Fu {}

interface InterfaceDemo {}

class Zi extends Fu implements InterfaceDemo {}

编译后产生的class文件(注意:接口也会编译成.class文件,但一定要明确它并不是类,而是另外一种引用数据类型
在这里插入图片描述
当内部类被static修饰后,只能直接访问外部类中的static成员,出现了访问局限性。
在外部其他类中,如何直接访问静态内部类的非静态的成员呢?new Outer.Inner().function();
在外部其他类中,如何直接访问静态内部类的静态成员呢?Outer.Inner.function();
注意:当内部类中定义了静态成员,该内部类必须也是static。
当外部类中的静态方法访问内部类时,内部类也必须是静态的。

内部类定义在局部时,注意这三项:
1、不可以被成员修饰符修饰。(public、private、protected、final、static、sychronized、native)
2、可以直接访问外部类中的成员,因为还持有外部类的引用。
3、但是不可以访问它所在的局部中的变量,只能访问final修饰的局部变量。(Java 8中局部变量自动使用final修饰)
4、外部类不能访问局部内部类,只能在方法中访问局部内部类,且访问必须在内部类定义之后。
下面我们介绍下匿名内部类:
1、匿名内部类其实就是内部类的简写格式。
2、定义匿名内部类的前提:内部类必须是继承一个类或者实现接口。
3、匿名内部类的格式:new 父类或者接口名() { //定义子类的内容 }
4、匿名内部类就是匿名子类对象,(是把定义类和创建对象封装成一体),是带有内容的对象。
5、建议匿名内部类定义的方法不要定义太多。
继承一个抽象类

abstract class AbsDemo {
    abstract void show();
}

class Outer {
    class Inner extends AbsDemo {
        @Override
        public void show() {
            System.out.println("重写show方法!!");
        }
    }
}

public class AnonymousInnerClass {
    public static void main(String[] args) {
        new AbsDemo() {
            @Override
            public void show() {
                System.out.println("匿名内部类重写show方法!!");
            }
        }.show();
        Outer.Inner inner = new Outer().new Inner();
        inner.show();
    }
}

在这里插入图片描述
因为匿名内部类没有名字,所以只能使用一次,它通常简化代码的编写。通过上面案例,我们知道继承一个类或者实现接口,最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是实现Runnable接口。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值