您的位置:首页 > 编程语言 > Java开发

JAVA三大特性初解

2016-02-25 09:20 429 查看
在介绍Java三大特性之前,我们来熟悉下,访问权限,因为在继承关系之前,我们应该知道,我们有哪些可以继承,哪些不可以,在继承后会出现成员变量的隐藏,静态的隐藏,以及多态重写后的访问到底是哪个对象。

在java中访问权限分为四种:

1.私有权限(private)
private可以修饰类成员,构造方法,方法成员,不能修饰外部类,被修饰为private的成员,
 只能在定义它们的类中使用,在其他类中不能调用,一般我们使用set,get方法,让调用类修改
 数据。一个内部类如果权限为私有的话,必须在外部类中得到这个内部类的对象,才可以访问
 内部类。
2.默认权限(default)
类,类成员,构造方法,方法成员变量,都能使用默认权限,即不写任何修饰权限,也就是同
 包权限,同包权限的元素只能定义在它们的类中,以及同包的类调用。
3.受保护权限(protected)
protected可以修饰类成员,构造方法,方法成员,不能修饰类,内部类是可以的。如果想要访
 问,必须在同包或者继承这个类。
4.公共权限(public)
public可以修饰类,类成员,构造方法,方法成员。是java中最大权限,在任何范围都是可以
 访问的。

在java中,类文件是以.java为后缀的代码文件,在每个类中最多只允许出现一个public类,如果为public那么这个类的名字必须和文件名一致。在类中,对于成员变量,如果未显示的初始化,那么java都会默认初始化。基本数据类型,一般为0,false;引用类型,为null;对于没有显示定义构造器,则编译器会自动创建一个无参构造器,如果定义了,则不会,所有的构造器默认为static。

初始化顺序:
当程序进行中,需要生成某个类对象时,jvm会先检查是否已经加载过这个类,如果没有,则先加载再生成对象,如果
已经加载,则直接拿过来。在堆里,如果长期不适用,gc回收器就会将对象进行回收。
例:
class Demo{
<span style="white-space:pre">	</span>static{
System.out.print("静态代码块");
}
public static void main(String[] args){
//两次new 在堆中开辟了两个对象空间,但是静态代码块却只会执行一次。
new Demo();
new Demo();
}
}
//输出结果:
//	静态代码块

</pre><span style="white-space:pre">		</span><span style="white-space:pre">	</span>在生成对象的过程中,会先初始化对象的成员变量,然后执行构造器。也就是说类中的变量在任何方法(包括构造器)调用<span style="white-space:pre">	</span>之前初始化。<span style="white-space:pre">		</span><pre name="code" class="java">class Demo2{
Inner inner =  new Inner();
public Demo2(){
<pre name="code" class="java"><span style="white-space:pre">		</span>System.out.print("构造函数");
}

public static void main(String[] args){
new Demo();
}
class Inner{
<span style="white-space:pre">	</span>public void Inner{
<pre name="code" class="java"><span style="white-space:pre">			</span>System.out.print("初始化");
}}

}
//输出结果:
//	初始化
//	构造函数


JAVA三大特性--继承

在java中继承使用关键字extends,当一个类没有继承任何父类时,默认继承Object。

    下面这张图是本人理解画的,初学者,有不对之处,请大牛提出,方便小弟学习!哈哈。



当子类继承父类时在方法区会先加载父类.class文件,然后加载子类.class文件,类中有静态与非静态,静态区域存放类中静态变量,静态方法,静态方法不依赖于对象,它依赖于类,所以调用时,直接使用类名.静态方法名或静态变量,子类中方法区,包含了一个this,和一个super,当实例化子类时,子类没有重写方法,实际调用的是super。this表示当前对象的引用,也就是谁new了这个类,this就代表谁,super表示父类对象的引用,在出现重写时,想要调用覆盖的父类方法,使用super.方法名。

new一个对象其实就是如果该文件没有被加载过时,先加载,然后在堆内存中,开辟空间,初始化完毕后,地址赋给栈中引用对象。

<span style="white-space:pre">	</span>class Animal{
public Animal(){
}
}
class Panda extends Animal{
public Panda(){
}
}


<span style="white-space:pre">	</span>class Animal{
public Animal(){
}
}
class Panda extends Animal{
public Panda(){
}
}


Panda继承于Animal,Panda为子类(也称为导出类),Animal为父类(也称为基类),在java中不允许多继承,如果想实现,我们可以实现接口,或者继承某个基类的最终子类,因为子类的功能是最多的。
1.子类继承父类的成员变量
当子类继承父类时,只能使用权限允许下的成员变量,比如public,protected,前面已经说到访问权限,default必须
在同包继承。在子类继承父类时,同名的成员变量,子类会屏蔽父类的成员变量,如果想调用的话,要通过关键字super。
2.子类继承父类时的方法
只是在继承方法上有差别,如果子类有相同的方法,并且参数类型,个数都相同,就是重写,这种情况如果想要调用父类
的方法时,需要用super关键字。
注意:隐藏和覆盖是不同的。隐藏是针对成员变量和静态方法的,而覆盖是针对普通方法的。
3.构造器
子类是不能继承父类的构造器的,如果父类有无参构造器,在子类构造器中想要显示调用父类有参构造器,必须在第一行
显式地用super关键字去调用,没有显式调用的话,系统会自动调用父类无参构造器,如果父类没有无参构造器,就必须
显式地去调用有参构造器,否则会报错。
面试题:
<pre name="code" class="java"><span style="white-space:pre">	</span>public class Test{
<span style="white-space:pre">	</span>public static void main(String[] args){
<span style="white-space:pre">	</span>	new C();
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>class A{
<span style="white-space:pre">	</span>public A(String type){
<span style="white-space:pre">	</span>System.out.println(type+" A");
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>class B{
<span style="white-space:pre">	</span>private A aa = new A("B");
<span style="white-space:pre">	</span>public B(){
<span style="white-space:pre">	</span>	System.out.println("B");
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>class C extends B{
<span style="white-space:pre">	</span>private A aa = new A("C");
<span style="white-space:pre">	</span>public void C(){
<span style="white-space:pre">	</span>//隐藏super() 仅仅代表先初始化父类数据,再初始化子类数据,初始化时,是按照分层初始化进行的
<span style="white-space:pre">	</span>System.out.println("C");
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>}
//输出结果为:
//	B A
//	B
//	C A
//	C



主要是考察类继承时构造器和初始化的调用顺序。父类的初始化以及构造器都是在子类前面的。在Java中,访问子类方法,如果子类有,访问子类的,如果没有访问父类。访问变量: 访问子类方法中变量:采用就近原则 如果局部变量有,使用局部变量全局变量有,是用全局父类全局变量JAVA三大特性--封装
万物皆对象。一个类就是一个对象,属性是用来描述同一类事物的特征,方法就是描述这一个事物的动作,封装就是将这个对象的特征和动作包装为一个类,方便其他类使用,一般我们先抽取,如,熊猫,狼,大狗熊,我们就可以抽取一个基类叫animal,它们有共同的属性,它们都会吃,都要喝水,如果它们有需要补充的其他动作的话,可以继承这个父类时,拓展。同样,在我们写代码的时候,安全性非常重要。有些数据(也称为JavaBean)我们提供一些get/set方。供其他程序员调用,而不用关心代码的细节,在客户端不暴漏信息。

简单的说,method(函数)就是封装的一种体现,当我们用别人写的类,调用别人的对象中的方法时,我们重来不关心,他是怎么实现的,我们关心的是,它的功能,它要我们传入什么参数,它返回给我们的是什么,就足够了。

private只是封装的一种体现,当出现private时,外界是无法放我们的数据,通过public方式对外公开,当然在我们编写类时,我们内部可以对成员数据进行操作,别人也是不知道的。当父类有私有属性时,子类通过继承他们的set/get方法也可以访问,个人认为,也是通过super关键字去访问的。继承破坏了封装性。

   

JAVA三大特性--多态

某一种事物,在不同时刻表现出来的不同状态。多态存在的三个必要条件是:一. 要有继承二. 要有重写三.
父类引用指向子类对象多态是一种运行期的行为,不是编译器的行为。比如:Animal a = new Dog();当使用多态方式调用方法是,首先检查父类是否有该方法,如果没有,则编译失败。如果有,调用子类重写方法。当使用多态方式访问成员变量时,访问的是父类成员变量,相同时,访问父类变量。static方法属于特殊情况,静态方法只能被继承,不能被重写,如果出现相同签名的静态方法,它对父类只起到隐藏的作用。调用时,用谁的引用调用哪个静态方法。如果想要调用子类中有而父类中没有的方法,需要向下转型。比如:
Dog1 dog = (Animal)a;多态中的成员访问特点:1.成员变量编译看左边,运行看左边2.构造方法创建子类对象时候,访问父类构造函数,对父类进行初始化3.成员方法编译看左边,运行看右边4.静态方法编译看左边,运行看左边。(静态和类相关,算不上重写,所以,访问还是左边的)由于成员方法存在方法重写,所以运行看右边。弊端:不能访问子类特有方法,如果想访问,向下转型,不安全,如果转换类型不是父类指向原子类对象,运行会报错。案例:
</pre><pre name="code" class="java">
<pre name="code" class="java"><span style="white-space:pre">	</span>class Fu{
String str = "hahaha";
public void show(){
System.out.println("Fu  show");
}
public static void nonono(){
System.out.println("Fu static");
}
}
class Zi extends Fu{
String str = "kukuku";
public void show(){
System.out.println("Zi  show");
}
public void method(){
System.out.println("Zi  method");
}
public static void nonono(){
System.out.println("Zi static");
}
}
class Zi2 extends Fu{
public void show(){
System.out.println("Zi2 show");
}
public void method(){
System.out.println("Zi2 method");
}
}

class Test{
public static void main(String[] args){
Fu f = new Zi();
f.show();
f.nonono();
System.out.println(f.str);
//f.method()	报错,父类中没有此方法
Zi z = (Zi) f;
z.method();
System.out.println(z.str);
f = new Zi2();
f.show();
//Zi zz = (Zi) f; 转换异常
}
}
//输出结果:
//	Zi  show
//	hahaha
//	Fu static
//	Zi  method
//	kukuku
//	Zi2 show
面向接口下一章
会讲道!


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: