前言
在Java中,我们经常做一件事情:
Object object = new Object();
对,就是new一个对象。但这句话到底是什么意思呢?向上/下造型时又为何能够new不同的东西呢?
new
new在Java中就是创建一个新的类型
在Java中,一个新的对象/普通类在没有被实例化之前,它的属性、方法等都不存在于内存中,只有在new了之后,这个类的一些东西在内存中才会真的存在,也即在new之后,这个类才能用
上图为
运行时数据区
,Java中通过new关键字+构造方法来创建一个对象Object object = new Object();
- 这句语句的前半部分意思为:在内存中分配一个变量,名字叫object,类型为Object,放入
局部变量区
- 这句语句的后半部分意思为:通过new关键字及构造方法Object()来在
堆(Heap)
中创建出一个Object对象
但在
堆区
中真正创建出一个Object对象后,还有一件事情要做…
引用
在
堆区
中真正创建出一个Object对象后,需要将这个对象在内存中的地址交给变量
object
,而object
就叫做引用
/引用变量
/变量
,其存储的值就是一个内存地址
,叫做引用地址
构造方法
在上面的内容中,我们还提到了
构造方法
是
new关键字
+构造方法
在堆区
创建出了一个实例对象
构造方法的作用,就是创建出一个
类的实例
,并对构造出来的这个类的实例
进行初始化
- 由此也不难理解为何构造方法名称必须与定义它的类名完全相同了。其不具备返回值类型(甚至连void也没有),
构造方法的调用
是在创建一个对象时使用new操作
进行的。类
中必定有构造方法
,若不写,系统自动添加无参构造方法
,接口
不允许被实例化
,所以接口
中没有构造方法
。构造方法
也不能被static
、final
、synchronized
、abstract
和native
修饰,其在初始化对象
时自动执行,一般不能显示的直接调用。- 当完成对
构造方法
的重载
后,Java编译系统会自动
按照初始化时最后面括号的参数个数及类型来自动对应判断,完成构造函数的调用构造方法
允许被重载
,无参构造方法
为默认构造方法
,与一般方法一样,构造方法
可以进行任何活动,但通常是用来进行各种初始化活动
- 构造代码块:
- 简介
在类中没与任何的前缀或后缀,并使用"{}"括起来的代码片段- 作用
给对象进行初始化,对象一建立就执行,而且优先于构造函数执行- 构造代码块和构造函数的区别
构造代码块
是给所有不同对象的共性进行统一初始化,构造函数
是给对应的对象进行初始化
向上/下造型
在实际情况中,我们可能会遇到如下情况:
class A{ public void myMethod(){ System.out.println("来自class A的myMethod方法"); } } class AOO extends A{ @Override public void myMethod(){ System.out.println("来自class AOO的myMethod方法"); } } class test{ public static void main(String[] args){ A test = new AOO(); AOO TEST = (AOO)test; } }
这很奇怪,为什么前面的
类型
与后面的构造方法
不匹配呢?为什么类A的对象
能被强转为类AOO的对象
呢?
向上造型
上例中的
A test = new AOO();
语句即为向上造型
依上文对这个语句进行分析:
- A test:在内存中创建一个名为
test
的变量,其数据类型为A
- new AOO():在堆内存中创建出一个
AOO
的实际对象,并将其地址传给变量test
这也就解释了为什么我们在使用
test
变量作为A的实例对象
使用某种公用方法
时,调用的却是AOO
中重写的公用方法
了
向上造型的意义在于提高程序的灵活性和可扩展性。通过向上造型,我们可以将一个实际类型为子类的对象当作其父类类型来处理,这意味着我们可以在不知道子类具体类型的情况下编写通用代码,这种特性也是Java多态性的基础之一,它使得程序更易于扩展和维护
向下造型
在
向上造型
部分我们通过解释A test = new AOO();
语句,确定了变量test
的数据类型为A
,但是实例对象为AOO
。也正因为变量test
的数据类型为A
,使得它只能调用A
中的方法与变量
,想要直接用test
调用AOO
中的方法与变量
只能通过强转的方式将test
强转为AOO
类型后才可以,此时的强转过程即为向下造型
向下造型的意义在于,它允许我们在需要时对已经向上造型的对象进行还原操作,从而可以使用子类独有的方法和属性,但需要注意的是,如果向下造型的对象不是实际上的子类对象,将会抛出ClassCastException异常