抽象类
定义:用关键字abstract关键字类修饰的一个类,叫做抽象类。
abstract class ClassName{
}
注意:1、抽象类必须被继承。
2、抽象类不能直接实例化。它只能作为超类,这一点与最终类(final类)正好相反。
3、抽象类中可以有抽象方法与普通方法,但抽象方法必须在抽象类中。
抽象方法
定义:用abstract来修饰的一个方法,叫做抽象方法。
abstract class ClassName{
abstract returnType abstractMethod([paramlist]);
}
注意:1、抽象方法必须被重写;
2、抽象方法在抽象类中只能声明,不能实现。即不能有{}。
3、定义抽象方法的类必须是抽象类。
4、子类继承抽象类时,必须重写所有的抽象方法子类才能成为普通类,不然子类也是抽象类。
例如:注意4例子
abstract class Animal{
abstract void eat();
abstract void sleep();
}
abstract class Dog extends Animal{
public void eat() {//抽象父类eat方法,但未重写sleep方法
//所以子类Dog也是一个抽象类。
}
// public void sleep() {
//
// }
}
接口
定义:接口就是方法定义与常量的集合。 从语法上讲:接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的的定义,没有方法的实现(没有普通方法和普通变量)。
实现:用interface关键字实现。
[public] interface interfaceName [extends Super Interface1, SuperInterface2,…]{
}
public class InterfaceTest {
public static void main(String[] args) {
student stu=new student();
stu.sleep();
System.out.println(stu.a);//输出接口person里面的常量
}
}
class student implements Agenf{//接口的使用,关键字implements
public student() {
}
@Override
public void eat() {
System.out.println("吃饭!!");
}
@Override
public void sleep() {
System.out.println("睡觉!!!");
}
}
interface person{
int a=10;
void eat();
}
interface Animal1{//声明接口
int b=100;
void sleep();
}
interface Agenf extends person,Animal1{//继承两个接口
@Override
default void sleep() {//按道理说这里是不可以实现方法的
//因为接口里面应该只有方法的声明,不能有实现。
//但这样也没有错,我也不知道为何!
}
@Override
default void eat() {
}
}
特点:1、与类的继承不同,一个接口可以继承多个父接口;
2、一个public接口只能定义在同名的.java文件中
接口的使用
1、用implements关键字来表示一个类的使用某个接口;
2、类可以使用接口定义的常量,但必须实现接口中定义的所有方法;
3、接口可以实现多重继承,即继承多个接口;
4、接口作用与抽象类相似,只定义原型,不直接定义方法内容;
5、接口中的方法和常量必须是public。
interface person{//其实是public interface peerson
int a=10;//public static final int a=10;
//public static final 省略
/* public abstract 省略 */ void eat();
}
JAVA8接口的新特性
java8允许我们给接口添加一个非抽象的方法实现,并且有方法体,只需使用关键字default或者static 即可,这个特征又叫扩展方法
//解释了上面代码里遗留的问题
interface Agenf{
default void sleep() {//按道理说这里是不可以实现方法的
//但是Java8过后可以,扩展特性。
}
@Override
default void eat() {
}
}
注意事项(重写规则):
1、子类继承的多个接口中同时存在同名,同参数的静态方法。子类在调用父类的静态方法的时候,需要通过父类名.静态方法名。若该静态方法如果在子类中也定义,它是不算被重写的。
2、如果两个接口的方法名和参数相同都是default方法,里面的实体不同,在子类中需要重写。
3、如果两个接口中的方法名,参数都相同的方法,一个接口是抽象方法,一个是default修饰的方法体。在类中也必须被重写。
4、如果一个类实现了一个接口的默认方法,同时又继承了另外一个类的方法。那么子类的方法优先跟父类的方法行为一致。
抽象类与接口异同点
相同点:
1、都必须通过其他类才能实现;
2、不能直接实例化。
不同:
1、抽象类是类,可包含变量及抽象方法的定义;
2、接口实质不是类,只含有类常量以及抽象方法的定义;
3、类只能单一继承,接口可以多继承。
4、接口只能public修饰符,类可以是任意修饰符;
5、继承强调关系:is a 接口强调功能: has a
内部类
定义:定义在类内部的类称为内部类,可以直接访问外围类相关成员。
说明:内部类编译后也会形成一个单独的.class,但它附属于其包含类。
分类:类体中的内部类 和 方法体中的内部类
一、类体中的内部类:
相当于类体中的成员变量,可以在类的内部和外部使用。
命令格式: 外围类类名+$+内部类类名.class
静态内部类:static 修饰,只能访问外围类静态的成员。
实例内部类:可以访问外围类所有成员。
实例内部类:
public class TestInnerClass {
public static void main(String[] args) {
Outer ou=new Outer();
//创建内部类对象
Outer.Inner inner=new Outer().new Inner();
inner.show();
}
}
class Outer{
private int age=10;//外部类成员变量
public void testOuter() {
System.out.println("这是外部类!");
}
class Inner{//普通内部类不能用static方法和属性
private int age=20;//内部类成员变量
public void show() {
int age=30;//方法成员变量
System.out.println("外部内的成员变量age:"+Outer.this.age);
System.out.println("内部内的成员变量age:"+this.age);
System.out.println("方法成员变量age:"+age);
}
}
}
静态内部类:
public class OuterTest2 {
public static void main(String[] args) {
//静态内部类的创建
Outer2.Inner2 inner2=new Outer2.Inner2();
}
}
class Outer2{
static class Inner2{
}
}
二、方法体中的内部类:只能在定义它的方法中或者代码块中使用,不能在外部使用。(又可以细分为有名字的内部类和匿名内部类)
命名格式:外围类名字+
+
数
字
+
内
部
类
类
名
.
c
l
a
s
s
外
围
类
类
名
+
+ 数字+内部类类名.class 外围类类名+
+数字+内部类类名.class外围类类名++数字.class
匿名内部类:
public class TestInn {
public static void test01(AA a) {
System.out.println("---------");
a.aa();
}
public static void main(String[] args) {
TestInn.test01(new AA() {//匿名内部类,只能使用一次
public void aa() {
System.out.println("new AA(){}");
}
});
}
}
interface AA{
void aa();
}
注意:匿名内部类没有访问修饰符,没有构造方法。
三、何时使用内部类
1、当第一个类能直接访问另外一个类中的成员时,将一个类定义为另一个类的内部类。
2、用于处理在GUI部分的事件处理机制中。
好处:可以直接使用包含类的变量和方法。(内部类只能在包含它的类中使用,同时把它看作该包含类的一段特殊代码。)