前言
学习Java基础是验证你有没有当指定某一处谈谈你的理解时,有没有更加深入的思考,有没有在学习语言时不贪多贪快的勇气。也许别人说2个月就能学完Java,但是你也可以相信自己,慢慢来总是更好,否则以后也会做多余的事情来弥补,甚至会越来越难理解后面细节内容。
我们要知道,对于一个对象来说,调用对象方法时,需要传递参数来接收我们发送的值。而在传递参数时,Java 是值传递(地址传递就是引用型数据了), 所以是将表达式的值复制给形式参数,对于引用型变量,因为传递的值是引用值,即地址,所以并不是复制对象实体,所以也就是说 可以改变对象的属性。
0x00、变量传递机制细节
那么变量的返回呢?方法中Java返回的变量是什么?因为除了基本数据以为,我们还想要存取对象实体,所以返回的是基本类型和返回引用类型,以下代码:
复制代码
代表调用时 Object p=GetNewObject(); 可以返回对象的引用类型给这个变量。
后来变量中出现了不定长参数这一需求,代表方法所需要的参数是不定长的,那么此时该怎么在Java中表示呢?以下代码可以看出在这个实施细节上,Java把这个当成了一个数组:
复制代码
代表在方法参数中使用省略号表示,并且是指示最后一个参数。调用的时候就可以这样 method(1,2,3,4); ,同时注意,还可以这样表示,public static void main(String ...argv),这也是一个在写代码中一定会遇到的细节。
0x01、上溯造型和多态
如果我们想使用同样的方法名,这个方法比较智能,可以根据你来什么不同的参数,就实现不同的功能,那么这是什么现象呢?这就引入了多态,多种状态的意思,也就是说一个程序中相同的名字表示不同含义的情况。
这里需要注意,多态有两种产生情况:
-
编译时多态
-
典型的重载,就是指使用多个同名不同参数类型的方法
-
代码:p.method() 和 p.method("will");
-
运行时多态
-
覆盖,就是子类对父类方法的覆盖
-
动态绑定,就是使用虚拟方法绑定
-
运行时调用对应的子类对象的方法
注意,多态的分类很重要,因为多态本身特性的原因提高了Java程序的抽象性和简洁性。下面可以深入理解一下。
0x02、动态类型与虚方法
我们该如何实现把派生类型当作基本类型呢,这里引入了一个新名词:上溯造型,即把派生子类先从基本父类处理起。在这个过程中子类会重载父类的方法,此时就叫运行时多态,实现的即指虚方法调用。 因为子类重载父类方法是系统根据运行时实例的类型来决定实例该对应哪个方法调用,所以叫虚方法调用。
这里注意,考虑被什么修饰的方***被自动实现虚方法调用呢?是final修饰的方法,一定会进行调用父类方法。这里指会自动绑定实例类型:
复制代码
所以根据不同的子类动态绑定实例就不同了。
代码实战:
在这个例子中, 展示虚函数showMe()如何根据它所关联的对象的引用来显示不同的文本 。当它与“Head”类型相关联时,它显示来自父类的消息。当它与“从属”类型相关联时,它显示来自子类的消息。
复制代码
与从属”类型相关联时,所以它显示来自子类的消息
0x03、非虚方法调用
这里要特别注意的地方,虚方法在方法被谁修饰时是不起作用的? 因为虚方法是根据实例的动态绑定,所以,有两个关键字都不可以使用虚方法, static 和 private , 首先我们要知道方法是可以被这两个修饰的,但是虚方法是不可以的。我们可以从这两个关键字编译后的字节码到底指令还可不可用, 直接看代码:
复制代码
0x04、总结
本教程总结了:
-
static的方法,与实例类型无关,所以以声明的类型为准
-
private的方法子类不可见,所以也不会被子类的虚方法调用
-
final的犯法子类的不能被重载和覆盖,所以不存在虚化问题
虚方法是Java编程语言中的一种方法。虚方法可以用多种方式实现,包括纯虚函数、虚构造函数或混合函数。虚函数用于实现运行时多态性,虚方法中就是依据变量传递的类型区分实现以及自动绑定的。