Java面向对象细碎知识
Java面向对象细碎知识
基础知识
引用变量:
引用类型变量(Reference Type Variable)是一种编程概念,主要存在于面向对象语言如Java、C#等中。引用类型变量并不直接存储对象的值,而是存储对该对象的引用或者说地址。这意味着它是一个指针或者句柄,指向内存中某个位置——存储了实际的对象数据
在Java中,除了基本数据类型(如int、char、double等)以外,其他的类型如类(class)、接口(interface)、数组(array)都属于引用类型。当声明一个引用类型变量时,实际上创建了一个引用
对象的内存分配
声明一个引用类型变量时,系统只为该变量分配了引用空间,并未创建具体对象;当用new为对象分配空间后,将对象的引用赋值给引用变量
类的声明:
1 |
|
成员方法:
-
方法是传值的,方法调用不会改变参数的值。即调用时参数传递给方法,就是赋值的过程
-
当对象作为参数时,参数的值是该对象的引用,这时对象的内容可以在方法中改变,但是对象的引用不会改变(这不意味着没有局部变量的概念),例如:
1 |
|
- 可变参数列表Varargs(类似 Python 的 args):定义格式:类型 … 参数名,可以使方法具有数目不定的多个参数,只能作为方法参数列表中的最后一个
类的构造方法:
所有的类都有构造方法,用来进行该类对象的初始化
1 |
|
-
方法名必须与类名相同
-
不能带返回值
-
不是类的方法,不称为类的成员
-
不能直接调用
-
如果在类定义中无构造方法,Java在编译时自动加入默认构造方法
-
一旦在类中有一个自己声明的构造方法,则默认的构造方法将不被加到类的定义中
this
关键字:
关键字this 用来指向当前对象本身
当类中有两个同名变量,一个属于类(类的成员变量),而另一个属于某个特定的方法(方法中的局部变量),使用this区分成员变量和局部变量
1 |
|
super
关键字:
super 指向该关键字所在类的父类。可以使用super访问父类被子类隐藏的变量或覆盖的方法
缺省是不带参数的构造方法。如果需要调用特殊的父类构造方法,则需在子类构造方法中第一行通过super( … )
调用
在方法中调用构造方法用this()
,调用父类的构造方法用super()
,而且该语句要出现在子类构造方法的第一行
1 |
|
访问控制:
-
成员变量和方法有4种访问级别:public, protected, default(package), private(带private 修饰符的属性、方法是不能被继承的,其他的都可以继承)
-
类有两种访问级别:public 或default
修饰符的作用范围:
Modifier | Same Class | Same Package | Subclass | Universe |
---|---|---|---|---|
public | Yes | Yes | Yes | Yes |
protected | Yes | Yes | Yes | No |
default | Yes | Yes | No | No |
private | Yes | No | No | No |
本人/克隆体 | 自己家 | 独立子女 | 所有人 |
注意:子类不能直接访问不在同一个包中的父类的protected变量和方法,只能通过自身(或子类)访问
protected访问修饰符允许以下情况:
- 同一包内的其他类可以访问protected变量和方法
- 不同包中的类,但仅限于子类,可以访问protected变量和方法
1 |
|
继承与初始化
- Java是单继承的,即只能从一个类继承,extends后类名只能有一个
- 单继承的优点:
- 代码更可靠
- 可以用接口弥补
- 用一个类实现多个接口,达到多继承效果
对象的初始化过程:
在对对象初始化时,顺序如下:
- 静态成员:
- 静态初始化块(
static
块)按照它们在类中出现的顺序(上溯到父类)执行 - 静态字段按照代码中声明的顺序进行初始化
- 注意,无论创建多少个类的对象,静态成员只会初始化一次,且发生在类被加载时
- 静态初始化块(
- 非静态成员(实例成员):
- 当创建类的实例时,首先初始化父类的实例变量和执行父类的构造函数(如果有的话),然后才初始化子类的实例变量,再最后是执行子类的构造函数
- 实例初始化块(非静态初始化块)按照它们在类中声明的顺序执行,这通常发生在构造函数之前
1 |
|
下溯造型和上溯造型:
-
上溯造型(Upcasting): 上溯造型是指将子类对象转换为父类类型的过程。在Java中,这个过程是隐式进行的。上溯造型之所以称为“上溯”,是因为在类的继承树结构中,是从子类“上溯”到父类。这样做是安全的,因为子类对象本来就是父类的实例。
1
2
3
4
5class Animal {}
class Dog extends Animal {}
Dog myDog = new Dog();
Animal myAnimal = myDog; // 这里发生了上溯造型Java中允许构造如下类型的数组:
1
2
3
4
5Employee [ ] staff = new Employee[1024];
staff[0] = new Manager();
staff[1] = new Worker();
staff[2] = new Employee();
… -
下溯造型(Downcasting): 下溯造型则是将父类类型的对象显式地转换为它的子类类型。这个过程是不安全的,因为在转换前并不能确定父类对象是否真的是目标子类的实例。下溯造型有可能失败,尤其是在运行时,如果没有正确的类型检查,将会导致
ClassCastException
异常。使用关键字(类型)
进行强制类型转换1
2Animal animal = new Dog();
Dog dog = (Dog) animal; // 这里发生了下溯造型在进行下溯造型之前,通常会使用
instanceof
关键字来检查对象是否可以安全地转换为指定的子类类型,防止运行时错误。1
2
3if (animal instanceof Dog) {
Dog dog = (Dog) animal; // 确保animal是Dog类型后再转换
}
内部类
- 内部类是在一个类的声明里声明的类。
1 |
|
- 可作为类的一个成员使用,一般只在外包类中调用
- 在类中定义一个类(私有内部类,静态内部类)
- 在方法中定义一个类(局部内部类,匿名内部类),意义:完善多重继承、实现事件驱动系统、闭包
编译器对类中内部类做的手脚:
- 在内部类中偷偷摸摸地创建了包可见构造器,从而使外部类获得了创建权限
- 在外部类中偷偷摸摸地创建了访问私有变量的静态方法,从而使内部类获得了访问权限。这样,类中定义的内部类无论私有、公有、静态都可以被包围它的外部类所访问
1 |
|