Q:子类对象的内存中,是否包含父类中定义的private
成员变量?
A:依然包含 private只是降低了访问权限,不影响内存布局和内存分布,外界无法访问,但是子类对象内存中依然包含。子类内存中包含父类所有的成员变量,无论是否是私有的
final
- 被final修饰的类不能被继承
- 被final修饰的方法不能被重写
- 被final修饰的变量,只能进行一次赋值
- 其他跟在Swift/Flutter中相似
常量
Java中常量一般写成 名称一般大写 static final修饰的称之为常量(约定俗成的叫法,final修饰也可以叫做常量)
private static final int MY_AGE = 1;
- 如果将基本类型或字符串定义为常量,并且在编译时就能确定值,编译器会使用常量值替换各处的常量名(类似于C语言的宏替换)
嵌套类
- 嵌套类:定义在另一个类中的类
public class OuterClass {
// 静态嵌套类
static class StaticNestedClass {
}
// 非静态嵌套类(内部类)
class InnerClass {
}
}
- 在嵌套类外层的类,称为:外部类(Outer Class)
- 最外层的外部类,称为:顶级类(Top-level Class)
内部类
内部类:没有被static
修饰的嵌套类,非静态嵌套类
- 跟实例变量,实例方法一样,内部类跟外部类实例相关联,
- 必须先创建外部类实例,然后通过外部类实例来创建内部类实例
- 内部类不能定义除了编译时常量以外的任何
static
成员 - 内部类可以直接访问外部类的所有成员(即使被声明为private)
- 外部类可以直接访问内部类实例的成员变量、方法(即使被声明为private)
- 内部类实例内存中有指向外部类实例的指针
OuterClass outer = new OuterClass();
// 通过外部类实例创建内部类实例
InnerClass inner = outer.new InnerClass();
静态嵌套类(Static Nested Class)
- 静态嵌套类: 被
static
修饰的嵌套类 - 静态嵌套类在行为上就是一个顶层类,只是定义的代码写在了另一个类中
- 对比一般的顶级类,多了一些权限
- 可以直接访问外部类中除了实例变量、实例方法之外的其他成员(即使被声明为private)
public class OuterClass {
private static int count = 1;
// 静态嵌套类
static class StaticNestedClass {
public void run() {
// 可以访问顶层类的成员 即使是private
OuterClass.count = 1;
// 不需要类名也可以直接访问外部类的成员
System.out.println(count);
}
}
}
什么情况使用嵌套类?
-
如果类A只在类C中使用,可以考虑把A嵌套在C中
- 封装性更好
- 程序包更加简化
- 增强可读性,维护性
-
如果类A需要经常访问类C的非公开成员,可以考虑将A嵌套在C中
- 也可以考虑将A隐藏起来,不对外暴露
-
如果需要经常访问非公共的实例成员,设计成内部类(非静态嵌套类),否则设计成静态嵌套类 (能静态尽量去静态)
局部类
-
局部类:定义在代码块中的类(可以定义在方法中,for循环中,if语句中等代码块中)
-
局部类不能定义除了编译时常量以外的任何static成员
-
局部类只能访问
final
或者 有效final的局部变量- Java 8开始,如果局部变量没有第二次赋值,就认为是有效final
-
局部类可以直接访问外部类的所有成员(即使被声明为private)
-
局部类只有被定义在实例相关的代码块中,才能直接访问外部类中的实例成员
public class LocalClass {
// 实例变量
public int age = 10;
// 静态初始化块 在类第一次初始化时调用
static {
class A {
public void test() {
// 跟实例相关的代码块中的局部类才能访问实例成员
// 会报错
// System.out.println(age);
}
}
A a = new A();
a.test();
}
// 初始化块 在类的构造函数中调用
{
class A {
public void test() {
// 跟实例相关的代码块中的局部类才能访问实例成员
System.out.println(age);
}
}
A a = new A();
a.test();
}
public void run(){
// count只赋值一次 被认为是有效fianl
int count = 0;
// 再次赋值的话就不被认为是有效final 局部类使用时会报错
// count = 10;
// 局部类
class A {
// 报错 不能定义除编译时常量以外的static成员
// public static int age = 0;
// 正确
public static final int age = 10;
public void test() {
// 可以访问final或者有效final的局部变量
System.out.println(count);
}
}
}
}
抽象类和抽象方法
-
抽象方法 :被
abstract
修饰的方法- 只有方法声明,没有方法实现
- 不能是
private
权限(因为定义抽象方法的目的就是让子类去实现) - 只能是实例方法,不能是类方法
- 只能定义在抽象类、接口中
- 抽象类:被
abstract
修饰的类- 可以定义抽象方法
- 不能实例化,但可以自定义构造函数
- 子类必须实现抽象父类中的所有抽象方法(除非子类也是一个抽象类)
- 可以像非抽象类一样定义成员变量,常量,嵌套类,初始化块,非抽象方法等
- 抽象类也可以完全不定义抽象方法
- 也就是说,抽象类比非抽象类多了一些抽象方法,但是不能实例化了
跟flutter中的抽象类似
网友评论