------- android培训、java培训、期待与您交流! ----------
一、抽象类
当一个类被abstract关键字修饰了之后,该类就是抽象类
抽象类的特点:
①方法只有声明,没有实现的时候,该方法就是抽象方法,需要被abstract修饰。抽象方法必须定义在抽象类中,该类就是抽象类。
②抽象类不可以被实例化。因为调用抽象方法没意义。
③一旦一个子类继承了某抽象类,该子类必须覆盖这个抽象类的所有抽象方法,该子类才能被实例化,否则该子类依旧是抽象类。
抽象类的细节:
①抽象类有构造函数么?
答:有,用来给子类对象初始化
②抽象类可以不定义抽象方法么?
答:可以的。但是很少见,目的就是不让该类创建对象。AWT的适配器对象就是这种类。通常这个类中飞方法有方法体,但是没有内容。如:
class Person{
void show(){
}
}
③抽象类的关键字不可以与哪些关键字共存?
答:private不行,因为抽象类的子类要覆盖抽象类的抽象方法,一旦私有化,就无法覆盖。
Static不行,因为static修饰的方法是静态方法,不需要对象就能够访问。用类.方法名就能访问,但是这样的抽象方法没有任何意义。
final不行,因为final修饰的类不能有子类,修饰的方法不能被覆盖。
④抽象类与一般类的异同点:
相同点:抽象类与一般类都是描述事物的,都在内部定义了成员。
不同点:1.一般类有足够的信息描述事物,而抽象类描述事物的信息可能不足。
2.一般类不能定义抽象方法,只能定义非抽象方法。而抽象类可以定义抽象方法,也可以定义抽象方法。
3.一般类可以被实例化,而抽象类不可以被实例化。
⑤抽象类一定是个父类吗?
答:是的。因为需要子类覆盖其方法后才可以被实例化。
⑥抽象类可以继承其他类么?
可以继承。例如Object就是个实体类,而其子类中却又抽象类。
二、接口
当一个抽象类中的方法都是抽象方法,属性只有常量的时候,这时可以将该抽象类用另一种表现形式,即接口。定义接口的关键字是interface。
接口中常见的成员(都有固定的修饰符):全局常量,抽象方法
全局常量:public static final xxx
抽象方法:public abstract xxx()
由此得出结论:接口中的成员都是公共的权限。接口中的成员前的修饰符一般都可以省略,但是除了abstract我们省略外,其他的修饰符我们一般不建议省略。方法前返回值类型根据具体情况而定。
1.接口的注意事项:
①接口不可以被实例化
②想要实现接口的类只有实现了接口的所有抽象方法,该类的对象才可以实例化,否则,该类是一个抽象类。
在java中不支持多继承,因为会出现调用的不确定性,所以java将多继承机制进行改良,在java中变成了多实现。即一个类可以实现多个接口。
2.使用接口的好处:
①一个类可以实现多个接口
②一个类在继承另一个类的同时还可以实现多个接口
③接口与接口之间是继承的关系,而且接口支持多继承
3.接口的特点:
①接口是对外暴露的规则 USB接口暴露在外侧
②接口是程序的功能扩展 USB接口可以接硬盘等硬件可以实现更多的功能
③接口的出现降低耦合性(解耦) USB接口可以即插即拔
④类与接口可以多实现,接口与接口可以多继承。 一个电脑可以拥有多个USB接口。
接口与抽象类的异同点:
共同点:都是不断抽取出来的抽象的概念
不同点:①抽象类体现继承关系,一个类只能单继承
接口体现实现关系,一个类可以多实现
②抽象类可以定义非抽象方法,供子类直接使用
接口的方法都是抽象方法,且都有固定修饰符。
接口的应用:以计算机和u盘用USB接口为例:
//暴露的规则
interface USB{
public void open();
public void close();
}
//实现规则
class Upan implements USB
{
public void open(){
System.out.println("Upan run...");
}
public void close(){
System.out.println("Upan close...");
}
}
//使用规则
public class Bookpc2{
public static void main(String[] args){
Upan upan=new Upan();
useUpan(upan);
closeUpan(upan);
}
public static void useUpan(USB u){
u.open();
}
public static void closeUpan(USB u){
u.close();
}
}
三、内部类以及匿名内部类
3.1 内部类
将一个类定义到另一个类的内部,这个类就叫做内部类。而另一个类就叫做外部类。由于另一个类访问一个类的私有变量时,需要使用这个类的set/get方法,比较麻烦,故设计内部类。举个例子,孙悟空与铁扇公主,人体类与心脏类。心脏类设计在人体类内部更好。当我们分析一个事物的时候,发现这个事物中还有事物,此时我们就应该设计内部类来解决相关的一些问题.
注意:内部类可以直接访问外部类的成员,外部类想要访问内部类,必须建立内部类的对象。当一个拥有内部类A的外部类B被加载进内存之后,编译得到的class文件的名称是B$A.class
①内部类修饰符:包括默认修饰符,public,private以及static。内部类的访问有以下几种方式。
1)当修饰符是public修饰符,默认修饰符以及static修饰符时,我们都可以直接访问内部类。对于public和默认修饰符,我们都必须建立内部类对象如下所示:
Outer.Inner in=new Outer().new Inner();
class Outer{
private int num;
class Inner{
Void show(){
System.out.println(num);
}
}
void method(){
Inner in=new Inner();
In.show();
}
}
class InnerDemmo{
public static void main(String[] args){
Outer.Inner in=new Outer().new Inner();//直接访问内部类
In.show();
}
}
2)对于static修饰符:
①当内部类的成员不是静态的,而内部类被static修饰时,我们直接访问内部类可以通过
class Outer{
private static int num;
static class Inner{
void show(){
System.out.println(num);
}
}
}
class InnerDemmo{
public static void main(String[] args){
Outer.Inner in=new Outer.Inner();//直接访问静态内部类中的成员
In.show();
}
}
②当内部类的成员也是静态的时候,如show方法也是静态的,此时我们可以直接通过以下方式访问内部类。注意:如果内部类中的成员是静态的,内部类也必须是静态的。
class Outer{
private static int num;
static class Inner{
static void show(){
System.out.println(num);
}
}
}
class InnerDemmo{
public static void main(String[] args){
Outer.Inner.show()//直接访问静态内部类中的静态成员
}
}
3)private修饰符封装内部类,此时在外部类需要提供公共方法来创建内部类对象来访问内部类中的成员。
细节:
①为什么内部类能够直接访问外部类的成员呢?
答:因为内部类隐藏的持有了外部类的引用,即外部类名.this
②内部类可以放在外部类的方法中,此时的内部类我们称为局部内部类,而此时方法中定义的局部变量需要在其前面加上final将其变为常量,才能访问。
3.2 匿名内部类
就是内部类的简写格式,其实就是一个匿名子类对象。匿名内部类的使用必须有前提:内部类必须继承一个外部类或者实现接口,格式如下:
New 父类or接口(){内部类内容(包括成员属性和成员方法)};(注意:匿名内部类并不是以大括号结尾,而是以";"结尾,这一点要尤为注意。)如:
abstract class Demo{
abstract void show();
}
class outer{
int num=4;
public void method(){
new Demo(){
void show(){
System.out.println(num);
}
}.show();//其实就是new 父类(){}.子类方法名
}
}
class InnerDemo2{
public static void main(String[] args){
New.outer().method();//调用匿名内部类对象
}
}
最终输出了num的值4
匿名内部类的应用:匿名内部类的使用场景之一:当函数参数时接口类型时,而且接口中的方法不超过三个。可以用匿名内部类作为实际参数进行传递。如
interface inter
{
void show1();
void show2();
}
class InnerDemo
{
public static void main(String[] args)
{
show(new inter()
{
public void show1()
{
System.out.println("这是匿名内部类的第一个方法");
}
public void show2()
{
System.out.println("这是匿名内部类的第二个方法");
}
});
}
public static void show(inter in)
{
in.show1();
in.show2();
}
/*相当于inter in=new inter();此时并不是接口实例化,
而是由于匿名内部类实现了接口,而匿名内部类的使用就是new父类名或者接口名(){内部类内容},而匿名内部类没有名字却有多个方法,所以我们就给接口定义了一个名字,才巧合的形成了这一种情况。*/
}
匿名内部类的细节:看下面一段程序
class Outer
{
void method()
{
new Object()
{
public void show()
{
System.out.println(“我是继承了object类的一个匿名内部类”);
}
}.show();
}
}
class OuterDemo
{
public static void main(String[] args)
{
new outer().method();
}
]
以上的程序是一个默认继承了Object类的匿名内部类,是可以执行的,但是如果我们将以上程序做以下修改:
class Outer
{
void method()
{
Object obj=new Object()
{
public void show()
{
System.out.println(“我是继承了object类的一个匿名内部类”);
}
};
obj.show();
}
}
class OuterDemo
{
public static void main(String[] args)
{
new outer().method();
}
]
修改后程序编译出错,这是什么原因呢?
答:因为在没有修改的时候,我们只是创建一个匿名内部类的对象,此时我们调用的时候该对象内部的方法,是可以通过的;而当我们修改之后,我们Object obj=new Object()这个语句体现出来的其实是多态性,即将匿名内部类对象向上转型,成为了Object类型,此时我们在调用,调用的是Object的方法,而由于其没有此方法,故会报错。