一、关于抽象类和接口之间的区别与特点
1.抽象类
抽象类的特点
1、抽象类和抽象方法都需要用abstract修饰
2、抽象方法必须在抽象类中,抽象类中可以没有抽象方法
3、抽象类不能直接创造对象(实例化)
4、抽象类的子类如果重写所有抽象方法,那么就是一个具体的类
5、抽象类的子类不重写所有抽象方法,那么子类还是一个抽象类
6、抽象类有构造方法,目的是让子类来调用构造方法初始化
7. 抽象类的成员特点:
成员变量:
既可以是变量也可以是常量。
构造方法:
有构造方法,用于子类访问父类数据的初始化。
成员方法:
抽象类中方法既可以是抽象的,也可以是非抽象方法。
在父类中:
非抽象方法:子类继承的事情,提高代码的复用性
抽象方法:强制要求子类做的事情。
8. 抽象类中注意的问题:
一个类如果没有抽象方法,可以是抽象类,即抽象类中可以完全没有抽象方法。
这样类的主要目的就是不让创建该类对象。
9. abstract关键字不可以与哪些关键字使用。
private 冲突;private修饰的成员不能被继承,从而不可以被子类重写,而abstract修饰的是要求被重写的。
final 冲突;final修饰的成员是最终成员,不能被重写,所以冲突,static 无意义;
static冲突;static修饰成员用类名可以直接访问,但是abstract修饰成员没有方法体,所以访问没有方法体的成员无意义。
2.接口
接口的特点
1. 接口中的方法,永远都被public来修饰
2. 接口中没有构造方法,也不能实例化接口对象
3. 接口中只有方法的声明,没有方法体
4. 接口中只有常量,如果定义变量,在编译的时候都会默认加上“public static final”
5. 接口中定义的方法都需要实现类来实现,如果实现类不能实现接口中的所有方法,则实现类需要定义为抽象类
6. 静态方法不能被子类重写(覆盖),因此接口中不定声明静态方法
7. 使用接口可以实现多继承
接口和抽象类的区别
1. 接口中所有的方法隐含都是抽象的,而抽象类则可以同时包含抽象和非抽象的方法
2. 类可以实现很多个接口,但是只能继承一个抽象类
3. 类可以不实现抽象类和接口声明的所有方法,在这种情况下,类也必须得声明成是抽象的
4. 抽象类可以在不提供接口方法实现的情况下实现接口
5. java接口中声明的变量默认都是final的,抽象类可以包含非final变量
6. java接口中的成员函数默认都是public的,抽象类中的成员函数可以是private,protected或者是public的
7. 接口是绝对抽象的,不可以被实例化。抽象类也不可以被实例化,但是如果它包含main方法的话是可以被调用的
二、构造方法
构造方法:构造器 初始化方法
new A():真正的对象,就是在堆内存中开辟的对象空间;
1)new 创建的意思,负责在堆内存中为对象开辟空间
2)A();构造方法,负责初始化对象
作用:1)用于初始化对象
2)定义一个类,即使类中什么内容都没有,它也存在一个隐藏的默认无参
的构造方法(其实是jvm提供的,保证至少有一个构造器初始化对象)
3)new之后跟的方法就是构造方法
构造方法和普通方法的区别:
构造方法:
1)没有返回值类型
2)构造方法名和类名一致
3)构造方法是被new调用的
4)构造方法中是可以使用return,但是用于结束函数(return;)而一般构造方法执行完了之后
会自动结束,不会显示return
5)构造方法可以调用普通方法
普通方法:
1)必须有返回值类型或者是无返回值(void)
2)只要有意义就可以
3)方法之间互相调用来使用的
4)普通方法中的return用于返回返回值和结束函数;
5)普通方法不可以调用构造方法
重载的构造方法:无参的构造方法和带参的构造方法
1)无参的构造方法初始化的对象的属性都是默认值
2)有参的构造方法都是创建对象并给对象的指定属性初始化值的
三、内部类
内部类特点:
内部类可以访问外部类的所有成员,包括私有
分类:
成员内部类
直接定义在类中的内部类
public class Outer{
//成员内部类
class Inner{
}
}
创建成员内部类的对象:
成员内部类的对象依赖于外部类的对象
外部类类名.内部类类名 对象引用=new 外部类().new 内部类();
内部类对外部类成员的访问:
内部类可以访问外部类的所有成员,包括私有
内部类中有两个this:
this:当前对象---内部类的对象
外部类类名.this:当前对象依赖的外部类对象
静态内部类
直接定义在类的内部,用static修饰的内部类
public class Outer{
//静态内部类
static class Inner{
}
}
静态内部类不依赖于外部类对象
创建静态内部类的对象只需要通过外部类的类名就可以
外部类类名.内部类类名 对象引用=new 外部类名.内部类类名();
静态内部类对外部类成员的访问:
静态内部类不能访问外部类的非静态成员,只能访问静态成员
局部内部类
定义在方法中的内部类
public class Outer{
public void method(){
//局部内部类
class Inner{
}
}
}
只能在定义局部内部类的方法内部创建局部内部类的对象
局部内部类可以访问外部类的局部变量,但是局部类访问的局部变量必须要用final修饰
局部变量会随着方法的调用完毕而消失,这个时候,局部对象并没有立马从堆内存中消失,还要使用那个变量。为了让数据还能继续被使用,就用fianl修饰,这样,在堆内存里面存储的其实是一个常量值。
匿名内部类
定义在方法中没有名字的内部类
将类的创建和对象的创建放在一起
匿名内部类分为两类:
继承方式的内部类
实现接口方式的内部类
实现匿名内部类的前提:
必须要有父类或者是接口
继承方式的内部类:
依赖于父类
new 父类(){
类中的内容
};
创建了一个继承了父类的子类的对象
1.创建了一个继承了父类的类---没有名字
2.创建了子类的对象
实现接口方式的匿名内部类:
依赖于接口
new 接口(){
实现类中的内容
};
创建了一个实现了接口的实现类的对象
1.创建了一个实现了接口的实现类--没有名字
2.创建了一个实现类的对象
什么时候使用实现接口方式的匿名内部类?
1.对实现类不会多次使用,可能就只使用一次
2.接口中的方法不多
final关键字
1)用final修饰的类不能被继承,没有子类;用final修饰的方法不能被子类的方法覆盖;
用final修饰的变量表示常量,只能被赋一次值。
final不能用来修饰构造方法,父类中用private修饰的方法不能被子类的方法覆盖。
final方法是不允许子类方法中写一个同样签名的方法的,但private的情况下,
你可以定义一个同样签名的方法。(final方法不能重载,private方法可以重载)
2)final类
final类不能被继承,因此final类的成员方法没有机会被覆盖,默认都是final的。
在设计类时候,如果这个类不需要有子类,类的实现细节不允许改变,
并且确信这个类不会载被扩展,那么就设计为final类。
3) final方法
如果一个类不允许其子类覆盖某个方法,则可以把这个方法声明为final方法。 使用final方法的原因有二:
第一、把方法锁定,防止任何继承类修改它的意义和实现。
第二、高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。
4)final变量(常量)
用final修饰的成员变量表示常量,值一旦给定就无法改变!
final修饰的变量有三种:静态变量、实例变量和局部变量,分别表示三种类型的常量。
从下面的例子中可以看出,一旦给final变量初值后,值就不能再改变了。
另外,final变量定义的时候,可以先声明,而不给初值,这中变量也称为final空白,无论什么情况,编译器都确保空白final在使用之前必须被初始化。
但是,final空白在final关键字final的使用上提供了更大的灵活性,为此,
一个类中的final数据成员就可以实现依对象而有所不同,却有保持其恒定不变的特征。
对于final类型的实例变量,可以在定义变量时,或者在构造方法中进行初始化;
对于final类型的静态变量,可以在定义变量时进行初始化,或者在静态代码块中初始化。
5)final参数
当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的值。
static关键字
1.静态方法中不能调用非静态方法
2.非静态方法可以调用静态方法
3.静态方法是不能被覆盖的
4.静态方法不需要有对象,可以使用类名调用。
5.Static方法是类方法,先于任何的实例(对象)存在。即Static方法在类加载时就已经存
在了,但是对象是在创建时才在内存中生成。而this指代的是当前的对象。
上代码:
public class Demo1 {
//final修饰的变量只能被赋值一次
//可以在声明时直接赋值
//public final String name="admin";//常量
public static final String name;//静态常量
//如果是静态常量可以在静态代码块中赋值
static{
name="李四";
}
//可以在构造代码块中赋值
/*{
name="张三";
}*/
//可以在构造方法中赋值
/*public Demo1(){
this.name="admin";
}*/
public void fun(){
//this.name="张三";
}
public final void method(){
}
//形参m被final修饰,m的值不能被改变
public void fun2(final int m){
int n=m+5;
/*m++;
m=m+5;*/
}
}
class demo2 extends demo1{
/* public void method(){
}*/
public void method(String name){}
}