您的位置:首页 > 职场人生

黑马程序员:java基础知识(二)

2014-05-28 23:18 176 查看
---------------------- ASP.Net+Unity开发 .Net培训、期待与您交流! ----------------------

三、接口

接口,是一个特殊的抽象类。定义接口的关键字——interface。

接口中常见的定义:①常量"static final";②抽象方法 "abstract 方法();"

接口中不可以创建对象,因为在接口中有抽象方法。当一个子类实现一个接口时,必须实现了该接口的所有方法以后才能创建对象,否则这个子类还是一个抽象类,不可实例化。

在java中,不支持多继承,但子类可以实现等多个接口。相对于类,接口有一个特殊,就是接口与接口之间可以实现多继承,并且只有接口才可以实现多继承。

例如:

class CA{}
class CB{}
class CC extends CA,CB{}  //这种做法是错的,java不支持多继承。

Interface IA{}
Interface IB{}
Interface IC extends IA,IB{}  //这是正确的,接口可以继承多个接口。
接口的特点:

①接口是对外暴露的规则。比如计算机的主板,它定义了一种规则,只要符合它的规则的产品就可以插到主板上使用。

②接口是程序功能的扩展;

③接口可以用来多实现;

④类与接口之间是实现关系,并且一个类在继承一个类的基础上,可以实现多个接口;

⑤接口与接口之间可以有继承关系,并且可以多继承;

⑥接口降低了耦合性。

四、多态

所谓多态,就是事物存在的多种形态。比如,猫就有两种形态,一个是猫,一个是动物。

1、多态的基本体现:父类的引用指向了子类的对象,父类的引用可以接收子类对象。例:interface IA{}

class CA implements IA{}

....

IA ia = new CA(); //父类的引用指向子类对象,这就是多态的基本体现。

2、多态的前提:类与类之间,必须有从属关系,可以是继承,也可以使实现。

3、多态的好处:使用多态可以大大的提高了程序的扩展性。

4、多态的弊端:父类的引用只能访问父类中既有的成员。也就是说,在子类中扩展的新成员,使用父类引用是访问不到的。

5、类型转换:

类型转换分为向上转型和向下转型。向上转型,也叫做类型提升,就是子类类型转换成父类类型。类似于,char型转换为int型,可以隐式转换。向下转型,就是将父类类型转换为子类类型。类似于,int型转换为char型,需要进行强制类型转换。

在使用多态时,父类的引用不能访问子类的中特有的成员,所以我们往往需要将父类的引用转换成子类类型。例如:

Super sp = new Sub();//父类引用指向子类对象

Sub sb = (Sub)sp;//将父类引用转换成子类类型

在进行强制类型转换时,切记不能将父类的对象转换成子类类型。多态中,自始至终都是子类对象在做变化。例如:

Super sp = new Super();
Sub sb = (Sub)sp;//这种做法将会出现类型转换异常:ClassCastException
//在进行类型转换时,下面这种情况也会出现类型转换异常.
class Super{}
class Sub1 extends Super{}
class Sub2 extends Super{}
……
Super sp = new Sub1();
Sub2 sb2 = (Sub2)sp;//这种类型转换也会出现类型转换异常。
这是什么原因呢?可以这么解释一下,猫和狗都属于动物,想让一只猫强制转换成一条狗,当然是不行的。
那怎样避免出现类型转换异常呢?java中提供了一个关键字——instanceof。该关键字用来判断一个引用变量是否属于某个类型。沿用上面的例子:
Super sp = new Sub1();//父类引用指向了子类Sub1的实例对象
“sp instanceof Sub1” //这个判断将返回true
“sp instanceof Sub2” //这个判断将返回false
所以在使用强制类型转换时,我们可以利用instanceof来判断引用的类型,避免类型转换异常。即:

if(sp instanceof Sub1){
Sub1 s1 = (Sub1)sp;
}else if(sp instanceof Sub2){
Sub2 s2 = (Sub2)sp;
}
6、多态中成员的特点:

①非静态成员函数:在编译时期参照引用变量所属类的成员函数,在运行时期参照所创建的对象的成员函数。举例说明:

class Super{
void print1(){System.out.print("super")}
}
class Sub extends Super{
void print1(){System.out.print("sub1")}
void print2(){System.out.print("sub2")}
}
……
Super sp = new Sub();
sp.print1();//编译正常通过,因为Super类中有print1这个方法,此处输出的结果是“sub1”,因为print1()方法已经被子类覆盖。
sp.print2();//编译不通过,因为Super类中没有print2这个方法。
所以,成员函数在多态中,编译时看左边,运行时看右边。

②成员变量:无论是在编译时还是运行时,都参照引用变量所属的类(左边)。

③静态成员:无论是在编译时还是运行时,都参照引用变量所属的类(左边)。

五、内部类

1、内部类的访问规则:

①内部类可以直接访问外部类的成员,包括私有成员。之所以可以直接访问,是因为内部类中持有了一个外部类的引用:Outer.this

②外部类访问内部类,须要创建内部类的对象。

内部类对象的创建:Outer.Inner io = new Outer().new Inner();

内部类是外部类的成员,与普通的成员,可以使用成员修饰符修饰。例如,static、final等。

2、静态内部类:

静态内部类对象的创建:Outer.Inner io = new Outer.Inner().

外部类中访问内部类的非静态成员的方式:new Outer.Inner().非静态成员

外部类中访问内部类的静态成员的方式:Outer.Inner.静态成员

需要注意的是,①如果内部类中定义了静态成员,则该内部类必须是静态的;②外部类的静态方法不能访问非静态的内部类;③外部类的静态方法可以直接访问静态的内部类。例如:

class Outer{
static void function(){
Inner.show();//错误的方式
new Inner().show();//这也是错的
new Outer().new Inner().show();//这也是正确的,上面②的说法是错的?但老师是这么说的。
}
class Inner{
void show(){}
}
}
3、局部内部类:

类似于局部变量,定义在方法或代码块中。局部内部类不能是静态的;不可以被成员修饰符修饰;他仍然可以直接访问外部类的成员,因为它仍然持有外部类的引用;可以访问该局部中被final修饰的变量,没有被final修饰的变量该内部类不能访问。例:

class Outer{
void function(){
int x = 1;       //没有final修饰符
final int y = 2; //有final修饰符
class Inner{
void show(){
System.out.println(x); //不可以访问
System.out.println(y); //可以访问
}
}
}
}
4、什么时候使用内部类?

类是对事物的描述,所以当某个事物内部还有事物时,我们就使用内部类来描述。例如,人体是一个事物,也就是一个类,人体内部还有心脏之类的事物,这是人体这一事物的内部事物,所以心脏这一事物就使用内部类来描述。就说,人体是外部类,心脏是内部类。

5、匿名内部类

顾名思义,就是没有名字的内部类,是内部类的简写格式。定义一个匿名内部类的前提是,该内部类必须有父类,可以是继承一个类或实现一个接口。

匿名内部类的定义格式:new 父类或接口(){ 定义子类内容 }; 。其实就是创建了父类或接口的匿名子类对象,而且是一个“带内容”的对象。

例:

interface Super{
void show1();
void show2();
}
class Outer{
//方式一:
void function1(){
new Super(){
public void show1(){
System.out.println("show1");
}
public void show2(){
System.out.println("show2");
}
}.show1();//创建了一个匿名内部类,并调用的内部类的方法show1
}
//方式二:
void function2(){
Super sp = new Super(){
public void show1(){
System.out.println("show1");
}
public void show2(){
System.out.println("show2");
}
};//创建了一个匿名内部类,并创建一个接口的引用指向这个匿名内部类。
sp.show1();
sp.show2();
}
}
上面的两种匿名内部类的创建方式中,方式二更为灵活。从方式二中,我们可以看出,匿名内部类的使用,也是多态的一种体现。但不管哪种方式,内部类必须全部实现父类或接口的抽象方法,因为内部类不能是抽象类。如果父类中的抽象方法太多,那么创建匿名内部类时,就显得很臃肿。所以,当父类或接口中的抽象方法太多时,不建议使用匿名内部类。使用匿名内部类时,内部类中定义的方法最好不要超过3个。

---------------------- ASP.Net+Unity开发 .Net培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: