Java 权限修饰符、final和接口
1. 权限修饰符(访问控制符)
1.1 概述
在Java中提供了4种访问权限,使用不同的访问权限修饰符时,被修饰的内容会有不同的访问权限。
- public:公共的
- protected:受保护的
- default:默认的(可以不填)
- private:私有的
用于修饰:类、(静态)成员变量、(静态)成员方法、构造方法
1.2 不同的权限修饰符,访问的能力图表
· | public | protected | default | private |
---|---|---|---|---|
同一类中 | √ | √ | √ | √ |
同一包中(子类与无关类) | √ | √ | √ | |
不同包的子类(父类和子类) | √ | √ | ||
不同包中无关类 | √ |
权限范围大小:public ->protected ->default ->private
1.3 权限修饰符的使用情况
default 不常用,通常可以省略代码
public 提供给其他类使用的成员
protected 想要给子类继承的成员
private 封装:为了保障成员变量的安全性,给这些变量设置为私有的,隐藏细节。但是提供给外部访问这个成员变量的方法 get/set 方法。
2. final
2.1 概述
通过继承的学习,我们可以知道,子类可以在父类的基础上改写父类内容,例如使用方法重写。但是,为了避免出现随意改写父类内容的情况出现,Java提供了final关键字,用于修饰不可改变的内容。
*final:不可改变的、最终的。可以用来修饰类、方法和变量
修饰类:类不能被继承
修饰方法:方法不能被重写
成员变量:变量不能被修改,必须初始化
局部变量:变量不能被修改,必须初始化
引用类型变量:引用地址不能被修改,但是内容可以修改
被final修饰的常量名称,一般有书写规范,所有字母都大写。
2.2 使用方法
2.2.1 修饰类
使用格式:
final class 类名{
}
2.2.2 修饰方法
使用格式:
修饰符 final 返回值类型 方法名 (参数列表){
//方法体
}
2.2.3 修饰变量
局部变量
public class Demo01Final {
public static void main(String[] args) {
int a= 10;
System.out.println(++a);
//final 修饰局部变量,只能一次赋值
final int b = 20;
//b=30;
System.out.println(b);
byte b1 =57;
b1 = 23+32;
byte b2 = 12;//变量相加,不确定范围,所以会出错
//b1=b2+10;
final byte b3 =23;//常量和字面量相加,范围没有超过127,可以执行
b1 = b3+34;
}
}
成员变量
public class Demo02Final {
int a = 10;
//final修饰成员变量,必须初始化:声明的同时,每个构造方法中写,或者在代码块中写。
final int b;
Demo02Final(){
b= 10;
}
Demo02Final(int a){
b=20;
}
// {
// b=10;
// }
public static void main(String[] args) {
Demo02Final demo2 = new Demo02Final();
demo2.a++;
System.out.println(demo2.a);
//b是常量,不能再改变值
//demo2.b++;
}
}
引用变量
import com.aaa.security.Cat;
import java.util.Arrays;
public class Demo05FinalVariable {
public static void main(String[] args) {
final int[]a= {1,2,3,4,5};
//final修饰引用类型变量,引用地址不能变,但是内容可以变
a[0]=3;
System.out.println(Arrays.toString(a));
int []b = {1,2,3,4,5};
System.out.println(Arrays.toString(b));
System.out.println(b);
b = new int [4];
System.out.println(Arrays.toString(b));
System.out.println(b);
//a = new int [4];
final Cat cat = new Cat();
//cat = new Cat();
cat.a_public = 100;
System.out.println(cat.a_public);
}
}
3. 方法的重写(补充内容)
1.子类中方法名和参数列表要和父类中一致。
@Override 检测这个方法是不是重写,方法语法不符合,会出现报错。
如果语法符合,没有加 @Override ,也属于重写。
2.子类中的权限,【大于等于】父类中的方法权限
带有private的属于私有的内容不能被重写。
3.子类中的返回值,【小于等于】父类中的返回类型
引用类型:
可以小于等于:
Zi->Fu->Object (√)
Fu->Zi (×)
基本数据类型,只能相同
Fu fu = new Zi(); (√)
Zi zi = new Fu(); (×)
4.static(类方法)不能被重写
注:方法重写的快捷键使用 Alt + insert 可以调出重写页面。
重写和重载的区别
4. 接口
4.1 接口的概述
接口,是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量、构造方法和成员方法,那么接口的内部主要就是封装了方法,包含了抽象方法,公共的静态常量(public static final)(JDK 7及以前),默认方法和静态方法(JDK8),私有方法(JDK9)。
接口的定义,他与定义类方式相似,但是使用interface关键字。他也会被编译成.class文件,但是它并不是类,而是另一种引用数据类型。
当前已学习的引用类型有:数组,类,接口。
接口使用的时候,他不能创建对象,但是可以被实现(implements)。一个实现接口的类,需要实现接口中所有的抽象方法啊,创建该类对象,就可以调用方法了,否则它必须是一个抽象类。
4.2 接口的格式
public interface InterfaceDemoB {
//JDK7只能有公开的抽象方法
void method1();
//JDK8 默认方法 - 通常用来做功能扩展
default void method2(){
System.out.println("JDK8 才支持的默认方法");
}
//JDK8 静态方法
static void method3(){
System.out.println("JDK8 才支持的静态方法");
}
//JDK9 私有方法
private void method4(){
System.out.println("JDK9 才支持的私有方法");
}
}
4.2 接口的使用步骤
1.接口不能直接new对象,需要一个实现类来实现接口
public class A implements InterfaceA{
}
将接口中所有持续方法 覆盖重写(实现)
2.创建实现类对象,调用方法
注意事项:实现类没有覆盖重写(实现)所有的抽象方法,这个实现类就必须是抽象的
4.3 四种方法的代码演示
接口的定义:InterfaceAbstractA.java
public interface InterfaceAbstractA {
//定义抽象方法
void abstractMethod1();
void abstractMethod2();
//定义默认方法,可继承也可重写,二选一
default void default_fly(){
System.out.println("飞?");
methodPrivateA();
}
//添加了一个静态方法
//静态方法中,不能直接调用普通成员方法
static void interfaceStaticA(){
System.out.println("静态方法的使用!");
interfacePrivateStaticA();
}
private static void interfacePrivateStaticA(){
//静态的私有方法:可以用来提取static方法中的共同代码,从而减少代码量
System.out.println("private static 静态私有方法!");
}
//私有方法 ————只能通过默认方法来调用
private void methodPrivateA(){
System.out.println("private!");
}
}
实现类:InterfaceAbstractAImpl.java
public class InterfaceAbstractAImpl implements InterfaceAbstractA{
//重写抽象方法
@Override
public void abstractMethod1() {
System.out.println("方法A实现!");
}
@Override
public void abstractMethod2() {
System.out.println("方法B实现!");
}
//重写默认方法
// @Override
// public void default_fly() {
// System.out.println("快乐的飞?");
// }
//调用静态方法,直接通过接口调用
//这里不需要重写静态方法
}
测试类:Demo01Interface.java
public class Demo01Interface {
public static void main(String[] args) {
InterfaceAbstractAImpl implA = new InterfaceAbstractAImpl();
//抽象方法的使用
implA.abstractMethod1();
implA.abstractMethod2();
System.out.println();
//默认方法的使用
//当类中重写了default方法,调用时就会直接调用重写后的
implA.default_fly();
System.out.println();
//静态方法的使用
InterfaceAbstractA.interfaceStaticA();
}
}
4.4 接口的多实现
在继承体系中,一个类只能继承一个父类。而对于接口来说,一个类是可以实现多个接口的,这个就叫做接口的多实现。并且,一个类能继承一个父类,同时实现多个接口。
实现格式:
public class Zi extends Fu implements InterfaceA,InterfaceB{
//重写接口中抽象的方法[一定要写]
//重写接口中默认的方法[不重名的时候可以不写]
}
接口和类之间的对接关系。
关系:
1.类和接口: 1 v n implements 实现
2.类和类 : 1 v 1 extends 继承
单继承 如果父类的方法和父接口中的默认方法重复,会优先调用父接口
3.接口和接口: 1 v n extends 继承
4.接口和类: 没有这种
抽象方法:
接口中,有多个抽象方法时,实现类必须重写所有的抽象方法。如果抽象方法中有重名的,只需要重写一次即可。
默认方法:
接口中,有多个默认方法时,实现类都可继承使用。如果默认方法有重名的,必须重写写一次。
静态方法:
接口中,存在同名的静态方法并不会冲突,原因是只能通过各自的接口中的默认值来访问静态方法。
4.5 接口的多继承
一个接口能继承另一个或者多个接口,这和类之间的继承比较相似。接口的继承使用 extends 关键字,子接口继承父接口。如果父接口中的默认方法有重名的,那么子接口需要重写一次。
注意:
子接口重写默认方法时,default关键字可以保留。
子类重写默认方法时,default关键字不可以保留。