目录
权限修饰符
它修饰的有:类, [静态]成员变量, [静态]成员方法, 构造方法
public: 公开的, 公共的
protected: 受保护的
(default): 默认的, 不加default关键字, 不写任何内容
private: 私有的
访问能力
权限范围由大到小: public->protected->default->private
作用
- default: 不常用, 练习时为了省略代码
- public : 想要提供给其他类使用的成员
- protected: 想要给子类继承的成员
- private: 所有的普通成员变量
封装: 为了保证成员变量的安全性, 给设置为私有的
提供给外部访问这个成员变量的方法 get/set
访问/修改私有成员变量
private int d_private = 40;
// 给外部获得 d_private 的方式
public int getD_private() {
return this.d_private;
}
// 给外部提供一个修改 d_private 的方式
public void setD_private(int d) {
this.d_private = d;
}
final
回顾static、abstract
- static: 静态的, 属于类的, 修饰成员变量/成员方法
有一些类的方法在使用时, 不需要创建对象,调用:类.方法 - abstract: 抽象的, 修饰类/成员方法
例:飞机大战中,move() 在所有的子类中都要重写, 父类中的move()方法体就没有意义,给一个空壳子
final
final: 最终的, 修饰类/成员方法/成员变量/局部变量
- 修饰类: 类不能被继承
- 修饰方法: 方法不能被重写
- 修饰成员变量: 变量不能被修改, 必须初始化
三种初始化方式:- 声明的同时
- 在每个构造方法中
- 在代码块中
代码块:执行每一个构造器之前先执行的代码
// final 修饰成员变量, 必须初始化: 声明的同时,每个构造方法中,代码块中
final int b;
{
b = 10;
}
- 修饰局部变量: 变量不能被修改, 必须初始化
byte b1 = 57;
b1 = 23 + 34; // 字面量相加, 虽然是int+int,加完发现在127范围内
byte b2 = 120;
报错 b1 = b2 + 34; // 变量相加, 不确定范围, 认定为int类型, 编译错误
final byte b3 = 23;
b1 = b3 + 34; // 常量和字面量, 加完发现范围没有超过
- 修饰引用类型变量: 引用地址不能被修改, 内容可以修改
final int[] a = {1, 2, 3, 4, 5};
// final 修饰引用类型变量, 引用-地址不能改变, 对象内容可以改变
a[0] = 3;
//报错 a = new int[4];
final Cat cat = new Cat();
cat.a_public = 20;
//报错 cat = new Cat();
常见的final类
String和Math
String不可变的原因: CharSequence - 字符序列 - 字符数组
底层实现: 字符数组 -> 字节数组 byte[] value
final value = 其他值
String str = “hello”;
str = “hi”;
常量的命名规则
常量: final 修饰的变量
全部大写, 多个单词拼接, 使用 _
EXIT_ON_CLOSE 见名知意
静态常量 Math.PI -> 常量字段
方法重写规范
- 子类中的方法名和参数列表要和父类中一致
@Override 检测这个方法是不是重写, 方法语法不符合重写, 就会报错
如果语法符合, 没有加@Override, 也属于重写 - 子类中的权限, [大于等于] 父类中的方法权限
public class Fu {
protected long m2() {
return 0;
}
}
public class Zi extends Fu {
@Override
public long m2() {
return 0;
}
}
-
子类中的返回值, [小于等于] 父类中的返回值类型
引用类型 小于等于: Zi -> Fu -> Object Fu->Zi(×)
基本数据类型, 只能相同
Fu fu = new Zi(); // √
Zi zi = new Fu(); // × -
静态方法/类方法, 不存在重写的概念
public static void m5() {
}
// @Override
// 类方法, 不存在重写的概念
// public static void m5() {
//
// }
接口
一种特殊的抽象类
抽象类: 可能会存在抽象方法
接口中没有构造方法
接口中有哪些
- 所有版本中
- 公开的抽象方法,默认添加public abstract
public abstract void m1();//练习时建议这么写
- 公开的静态常量
接口中的成员变量, 只支持public final static
- JDK8开始
- 静态的方法 static
属于接口的, 通过接口直接调用
静态方法中, 不能直接调用普通成员方法,能调用同是静态的方法 - 默认的方法 default
通常用来做接口功能的扩展, 可以在实现类中覆盖
public interface InterfaceDefault {
//公开的抽象方法
void methodAbs1();
//默认的方法
public default void defaultMethod() {
System.out.println("Default A");
}
}
public class InterfaceDefaultImpl implements InterfaceDefault {
// 实现接口中的抽象方法
@Override
public void methodAbs1() {
System.out.println("methodAbs1");
}
// 相当于将默认方法直接继承过来了,不用重写
}
public class InterfaceDefaultImplB implements InterfaceDefault {
//实现接口中的抽象方法
@Override
public void methodAbs1() {
System.out.println("methodAbs1 BBB");
}
// 重写了默认的方法
public void defaultMethod() {
System.out.println("Default BBBB");
}
}
public static void main(String[] args) {
InterfaceDefaultImpl impl = new InterfaceDefaultImpl();
// 调用普通方法
impl.methodAbs1();
// 调用默认方法, 类中如果没有这个方法, 向上级找
impl.defaultMethod();
InterfaceDefaultImplB implB = new InterfaceDefaultImplB();
implB.methodAbs1();
// 类中重写了接口的default方法, 调用时, 就会使用重写后的方法
implB.defaultMethod();
}
//打印
methodAbs1
Default A
methodAbs1 BBB
Default BBBB
- JDK9开始
- 私有方法 private
普通的私有方法: 为了给default方法中的公共代码提取, 实现代码复用
private void methodPrivateA() {
System.out.println("AAA");
System.out.println("BBB");
System.out.println("CCC");
}
default void methodDefaultA() {
System.out.println("默认方法A");
methodPrivateA();
}
静态的私有方法: 给static方法中公共代码提取的
static void methodStaticB() {
System.out.println("静态方法B");
methodPrivateB();
}
private static void methodPrivateB() {
System.out.println("AAA");
System.out.println("BBB");
System.out.println("CCC");
}
补充:
- 接口不是类, 所以没有子类, protected不能用
接口的使用步骤
- 定义接口
public interface InterfaceAbstractA {
// 定义抽象方法
void abstractMethod();
// 再添加一个抽象方法
void abstractMethodB();
// 又添加了一个静态方法
static void staticMethodC() {
System.out.println("static MethodC");
}
}
- 定义实现类implements, 实现接口。必须覆盖重写(实现)所有的抽象方法,否则这个实现类必须是抽象的。
public class InterfaceAbstractAImpl implements InterfaceAbstractA {
@Override
public void abstractMethod() {
System.out.println("AAAA");
}
@Override
public void abstractMethodB() {
System.out.println("BBBB");
}
}
- 创建实现类对象,调用方法
public static void main(String[] args) {
// 3.创建实现类对象
InterfaceAbstractAImpl implA = new InterfaceAbstractAImpl();
// 调用方法
implA.abstractMethod();
implA.abstractMethodB();
// 调用静态方法, 不能用实现类调用, 写法错误
// InterfaceAbstractAImpl.staticMethodC();
// 调用静态方法, 直接通过接口调用
InterfaceAbstractA.staticMethodC();
}
关系
1.类和接口: 1 v n implements 实现
一个类一定有唯一的父类, 可以有多个父接口
- 实现多个接口, 要将这些接口中所有的抽象方法都实现掉
- 父类中有抽象方法, 也要实现掉
- 如果多个接口中,有重复的抽象方法,实现一次即可
- 如果多个接口中,有重复的default方法,必须要重写一个
2.类和类 : 1 v 1 extends 继承
3.接口和接口: 1 v n extends 继承
一个接口可以继承多个接口
4.接口和类: 没有
public abstract class Fu {
public abstract void methodAbsC();
public void method1() {
}
}
public interface InterfaceA {
void methodAbsA();
default void methodDefaultA(){
System.out.println("InterfaceA methodDefaultA");
}
}
public interface InterfaceB {
void methodAbsA();
default void methodDefaultA() {
System.out.println("InterfaceB methodDefaultB");
}
}
public interface InterfaceC extends InterfaceA, InterfaceB {
void methodAbsC();
// 能用的有:
// 1.InterfaceA 中的抽象方法和默认方法
// 2.InterfaceB 中的抽象方法和默认方法
// 3.自己的抽象方法和默认方法,私有,静态
// 4.如果父接口中有重名的默认方法, 必须重写
default void methodDefaultA() {
}
}
public class Zi extends Fu implements InterfaceA, InterfaceB {
//重写父抽象类中的抽象方法
@Override
public void methodAbsC() {
}
@Override
public void methodAbsA() {
}
public void methodZi() {
}
public void methodDefaultA() {
}
}
public class Demo01 {
public static void main(String[] args) {
Zi zi = new Zi();
// zi 中可以调用的方法
// 1.Fu中继承的, 重写的
// 2.所有的接口中重写的, 继承的default
// 3.自己写的
zi.methodDefaultA();
}
}
接口作为方法参数/返回值
具体使用的都是接口的实现类对象
public interface MyInterfaceA {
void methodAbs1();
void methodAbs2();
}
public class MyInterfaceAImpl implements MyInterfaceA {
@Override
public void methodAbs1() {
System.out.println("第一个抽象方法的实现");
}
@Override
public void methodAbs2() {
System.out.println("第二个抽象方法的实现");
}
}
public class MyInterfaceAImpl2 implements MyInterfaceA {
@Override
public void methodAbs1() {
System.out.println("第二个实现类的方法1");
}
@Override
public void methodAbs2() {
System.out.println("第二个实现类的方法2");
}
}
public class Demo {
// 接口类型作为方法参数
public MyInterfaceA haha(MyInterfaceA a) {
// a 调用的是哪个方法, 具体看传入的对象是哪个实现类
a.methodAbs1();
a.methodAbs2();
System.out.println("哈哈结束了!");
return new MyInterfaceAImpl();//简写,看下面
// 创建了一个接口的实现类对象, 向上造型为接口类型
/*MyInterfaceA a1 = new MyInterfaceAImpl();
// 接口类型的对象 返回
return a1;*/
}
public static void main(String[] args) {
Demo d = new Demo();
// 创建接口的实现类对象
MyInterfaceAImpl a = new MyInterfaceAImpl();
// 参数需要一个 MyInterfaceA 类型
// 实际参数: 可以是接口的实现类 对象
d.haha(a);
MyInterfaceAImpl2 a2 = new MyInterfaceAImpl2();
// 写法错误, 返回值类型规定是 MyInterfaceA
// MyInterfaceAImpl2 re = d.haha(a2);
// 正确写法
MyInterfaceA re = d.haha(a2);