权限修饰符和内部类
Posted lf-637
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了权限修饰符和内部类相关的知识,希望对你有一定的参考价值。
一、final关键字
final关键字代表最终、不可改变的。学习了继承后,我们知道子类可以在父类的基础上改写父类内容,比如方法重写。为了避免随意改写的情况发生,Java提供了 final 关键字,用于修饰不可改变内容 。主要表现在使用final关键字后:
- 类:被修饰的类,不能被继承
- 方法:被修饰的方法,不能被重写
- 变量:被修饰的变量,不能被重新赋值
1. 常见四种用法
- 可以修饰一个类
- 可以修饰一个方法
- 可以修饰一个局部变量
- 可以修饰一个成员变量
① 修饰类
格式:
public final class 类名称{
//....
}
含义:当前这个类不能有任何子类(可以理解为太监类)。所以也无法对成员方法进行覆盖重写
② 修饰方法
格式如下:
修饰符 final 返回值类型 方法名(参数列表){
//方法体
}
含义:用final修饰的方法可以被继承,但是不能被子类的重写
注意:对于类和方法来说,abstract和final关键字不能同时使用。因为矛盾
③ 修饰变量
-
修饰局部变量
-
一旦使用final变量修饰局部变量,则此变量就不能进行更改
-
对基本类型来说,不可变指的是变量中的数据不可改变
-
public class FinalDemo1 { public static void main(String[] args) { // 声明变量,使用final修饰 final int a; // 第一次赋值 a = 10; // 第二次赋值 a = 20; // 报错,不可重新赋值 // 声明变量,直接赋值,使用final修饰 final int b = 10; // 第二次赋值 b = 20; // 报错,不可重新赋值 } }
-
-
对引用类型来说,不可变指的是变量中的地址值不可改变
-
public class FinalDemo2 { public static void main(String[] args) { // 创建 User 对象 final User u = new User(); // 创建 另一个 User对象 u = new User(); // 报错,指向了新的对象,地址值改变。 // 调用setName方法 u.setName("张三"); // 可以修改 } }
-
-
-
修饰成员变量
- 对于成员变量来说,如果使用final关键字进行修饰,那么这个变量也是不可变
- 由于成员变量具有默认值,使用了final之后没有默认值,必须手动赋值
- 对于final的成员变量,要么直接赋值,要么通过构造方法赋值
- 通过构造方法赋值,必须保证类中所有重载的构造方法都最终会对final中的成员变量进行赋值
二、权限修饰符
Java中提供了四种访问权限符,访问权限大小:public > protected > (default) > private
不同权限的服务能力:
public | protected | default(空的) | private | |
---|---|---|---|---|
同一类中 | √ | √ | √ | √ |
同一包中(子类和无关类) | √ | √ | √ | |
不同包的子类 | √ | √ | ||
不同包中的无关类 | √ |
可见,public具有最大权限。private则是最小权限 。编写代码时,如果没有特殊的考虑,建议这样使用权限
- 成员变量使用 private ,隐藏细节
- 构造方法使用 public ,方便创建对象
- 成员方法使用 public ,方便调用方法
注:不加权限修饰符,其访问能力与default修饰符相同
三、内部类
很多时候我们创建类的对象的时候并不需要使用很多次,每次只使用一次,这个时候我们就可以使用内部类
1. 概述
内部类就是在一个类的内部在定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了
内部类不是在一个java源文件中编写俩个平行的俩个类,而是在一个类的内部再定义另外一个类。 我们可以把外边的类称为外部类,在其内部编写的类称为内部类
2. 分类
内部类分为四种 :
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
① 成员内部类
-
成员内部类 :定义在类中方法外的类
-
定义格式:
-
class 外部类 { class 内部类{ } }
-
在描述事物时,若一个事物内部还包含其他事物,就可以使用内部类这种结构。比如,汽车类 Car 中包含发动机类 Engine ,这时, Engine 就可以使用内部类来描述,定义在成员位置
-
class Car { //外部类 class Engine { //内部类 } }
-
-
访问特点
- 内用外,随意访问。即内部类可以直接访问外部类的成员,包括私有成员
- 外部类要访问内部类的成员,必须要建立内部类的对象
-
使用成员内部类
- 间接方式:通过外部类的对象调用外部类的方法,在里面间接使用内部类
- 直接方式:记住格式
外部类名称.内部类名称 对象名 = new 外部类名称().new 内部类名称();
-
内部类的重名变量访问
- 格式:
外部类名称.this.外部类成员变量名
- 格式:
② 静态内部类
使用static修饰的内部类就叫静态内部类 。下面复习static的用法:
(1). 一般只修饰变量和方法,平常不可以修饰类,但是内部类却可以被static修饰
(2). static修饰成员变量:整个类的实例共享静态变量
(3). static修饰方法:静态方法,只能够访问用static修饰的属性或方法,而非静态方法可以访问static修饰的方法或属性
(4). 被static修饰了的成员变量和方法能直接被类名调用
(5). static不能修饰局部变量,平常就用来修饰成员变量和方法
注意:
- 静态内部类能够直接被外部类给实例化,不需要使用外部类对象
Outer.Inner inner = new Outer.Inner();
- 静态内部类中可以声明静态方法和静态变量,但是非静态内部类中就不可以声明静态方法和静态变量
③ 局部内部类
局部内部类是在一个方法内部声明的一个类,可以访问外部类的成员变量及方法。如果局部内部类中要访问该内部类所在方法中的局部变量,那么这个局部变量就**必须是有效final修饰的 **
public class Outer {
private int id;
//在method01方法中有一个Inner内部类,这个内部类就称为局部内部类
public void method01(){class Inner{
public void in(){
System.out.println("这是局部内部类");
}
}
}
}
局部内部类一般的作用跟在成员内部类中总结的差不多 ,但有两点要注意
-
在局部内部类中,如果要访问局部变量,那么该局部变量要用final修饰
-
new出来的对象在堆内存中,而局部变量在栈内存中,是跟着方法走的。若方法运行结束将立即出栈,此时局部变量会跟着消失。这个时候局部内部类对象在想去调用该局部变量,就会报错,因为该局部变量已经没了
-
当局部变量用fanal修饰后,就会将其加入常量池中,即使方
法出栈了,该局部变量还在常量池中,局部内部类也能够调用。所以局部内部类想要调用局部变量时,需要使用final修饰。 -
public void methodOuter(){ final int num = 10; } class myInner(){ public void methoeInner(){ System.out.println(num); } }
-
-
局部内部类不能通过外部类对象直接实例化,而是在方法中实例化出自己来,然后通过内部类对象调用自己类中的方法
④ 匿名内部类【重点】
如果接口的实现类(或者是父类的子类)只需要使用唯一的一次,此时可以省略该类的定义,改为使用匿名内部类
-
概述
- 匿名内部类是最常用的一种内部类 ,是内部类的简化写法。
- 它的本质是一个带具体实现的父类或者父接口的匿名的子类对象。
- 如当使用一个接口时,需要做包括定义重写在内的好几步操作 。而使用匿名内部类就能简化成一步
-
前提
- 匿名内部类必须继承一个父类或者实现一个父接口
-
格式
-
new 父类名或接口名(){ //覆盖重写所有抽象方法 };
- new 代表创建对象的动作
- 接口名称就是你们内部类需要实现哪个接口
- 大括号内的是匿名内部类
-
-
注意的问题
- 匿名内部类在创建对象的时候,只能使用唯一一次。如果希望多次创建对象,那就使用单独打印的实现类
- 匿名对象在调用方法的时候,只能使用唯一一次。如果希望多同一对象调用多次方法,那就必须给对象起个名字
- 匿名内部类是省略了实现类/子类,但是匿名对象是省略了对象名称。注意,两者不同。
以上是关于权限修饰符和内部类的主要内容,如果未能解决你的问题,请参考以下文章