一、抽象类 & 抽象方法
-
抽象类
它是一种特殊的类,不能直接创建对象,而是用于被其他具体类继承。
要声明一个抽象类,需要使用关键字abstract来修饰类名。如果一个类中包含了至少一个抽象方法,那么这个类就必须声明为抽象类。子类继承抽象类时,必须实现所有抽象方法,除非子类本身也是抽象类。
理解:抽象类不能被实例化,比如动物这个概念,世界上没有叫“动物”这个东西的物种,不能被具体出来。 -
抽象方法
● 抽象方法只能有声明,不能有方法实现
● 如果类中有抽象方法,那么这个类必须被定义为抽象类;反之未必
● 抽象方法只能被定义为 public 或 protected 或 default,不能为 private,因为抽象方法要被继承,定义成private就不能被继承了。
● 抽象方法不能是静态的,因为抽象方法是用来定义接口或抽象类中的未实现的方法,而静态方法是属于类而不是对象的方法。抽象方法需要在具体的类中实现或者在继承抽象类的子类中被重写,而静态方法可以直接通过类名进行调用,不需要实例化对象。
抽象方法的一个实例:
@Test
public void test01() {
Dog_day03_1 dog = new Dog_day03_1();
dog.run();
dog.eat();
Cat_day03_1 cat = new Cat_day03_1();
cat.eat();
}
}
/**
* test01 抽象类
*/
abstract class Animal_day03_1 {
// 非抽象方法,有具体实现
public void run() {
System.out.println("The animal is running");
}
// 抽象方法只能有声明,不能有方法实现,只能被定义为 public 或 protected 或 default,不能为 private
public abstract void eat();
}
// 具体类 Dog 继承自抽象类 Animal
class Dog_day03_1 extends Animal_day03_1 {
@Override
public void eat() {
System.out.println("The dog is eating bones");
}
}
class Cat_day03_1 extends Animal_day03_1 {
@Override
public void eat() {
System.out.println("The cat is eating fish");
}
}
抽象方法是静态时的情况:
public void test02() {
test02_AbstractClass.noabstract_Method(); // 可以直接通过类名调用静态方法,输出“非抽象静态方法”
// AbstractClass.abstractMethod(); // 报错,无法直接调用抽象方法
}
}
abstract class test02_AbstractClass {
// 抽象方法,不能加static,会报错
// public abstract static void abstract_Method();
// 非抽象方法,可以加static
public static void noabstract_Method() {
System.out.println("非抽象静态方法");
}
}
二、final
final是一个关键字,用于表示一个不可变的实体。
● 在 Java 中 final 关键字可以被用来修饰类、方法和变量
● 用 final 修饰类时表示此类不可以被继承
● 用 final 修饰方法时表示此方法不可以被继承类覆盖
● 用 final 修饰成员变量时表示该变量是一个常量,在初始化后不能被改变
● 使用 final 关键字修饰类的静态变量,须在定义时或者在静态块中进行初始化
● 使用 final 关键字修饰类的实例变量,可以在动态块中、也可以在每个构造函数中进行初始化
● 使用 final 关键字修饰方法参数,表示此方法参数不能修改
三、abstract & final
● abstract final 不能同时用来修饰类
● abstract final 不能同时用来修饰方法
● static abstract 不允许。因为抽象方法的调用需要使用方法的动态绑定机制,因此静态方法不能是抽象方法
● private abstract 不允许。因为抽象方法必须要被继承类覆写,因此继承类必须能够访问抽象方法,所以抽象方法的访问权限不能是 private
● 给 abstract 方法赋 default 访问权限,编译允许,但不推荐。因为这样会造成其他包(package)的类无法继承这个抽象类,因为这个抽象方法对其他包(package)的类不可见
/**
* abstract final 不能同时用来修饰类
* 这两个关键字矛盾,无法同时用来修饰类
*/
//abstract final class test1 {
//
//}
/**
* abstract final 不能同时用来修饰方法
* abstract是抽象方法,需要在子类中进行实现,而final关键字表示方法是最终的,不能被子类重写
*/
//abstract final void test2() {
//
// }
/**
* static abstract 不允许
* 因为抽象方法的调用需要使用方法的动态绑定机制,因此静态方法不能是抽象方法
*/
//class MyClass {
// public static abstract void test3() {
//
// }
//}
/**
* private abstract 不允许
* 因为抽象方法必须要被继承类覆写,因此继承类必须能够访问抽象方法,所以抽象方法的访问权限不能是 private
*/
//abstract class test4 {
// private abstract void privateAbstractMethod();
//}
/**
* 给抽象方法赋予 default 访问权限,编译允许但不推荐
*/
abstract class test5 {
abstract void defaultAbstractMethod();
}
四、接口
接口概念
是Java中一种抽象的编程结构,它定义了一组方法的规范,但没有提供方法的具体实现。接口可以被看作是没有实例数据,并且所有方法都是抽象方法的抽象类。
接口继承
接口之间也可以继承,而且一个接口可以从多个接口继承。
接口实现:
@Test
public void test03() {
//Animal_interface_test03 dog = new Dog_interface_test03();
Dog_interface_test03 dog = new Dog_interface_test03();
dog.eat();
Bird_interface_test03 bird = new Bird_interface_test03();
bird.fly();
bird.eat();
System.out.println(bird.age);
}
// 接口简单实现
interface Animal_interface_test03 {
// protected void eat(); // 使用protected会报错 Modifier 'protected' not allowed here
void eat();
int age = 10;
}
interface Plane_interface_test03 {
void fly();
}
class Dog_interface_test03 implements Animal_interface_test03 {
public void eat(){
System.out.println("The dog is eating bones");
}
}
// 多继承
class Bird_interface_test03 implements Animal_interface_test03, Plane_interface_test03 {
public void eat() {
System.out.println("The bird is eating rice");
}
public void fly() {
System.out.println("The bird is flying");
}
}
在Java早期版本(Java 7及之前),接口中不能包含静态方法。从Java 8开始,引入了接口中的静态方法的概念。Java 8以后的版本允许在接口中定义静态方法,以提供更多的灵活性和实用性。使用时,静态方法不能被实例化对象调用,而应该通过接口名来调用。
public void test04() {
Dog_interface_test04 dog = new Dog_interface_test04();
dog.eat(); // 狗吃骨头,这是非静态方法
// dog.run(); // 这个是静态方法,静态方法不能被实例化对象调用,而应该通过接口名来调用。
Animal_interface_test04.run(); // 动物跑,这是静态方法,静态方法不能被实例化对象调用,而应该通过接口名来调用。
}
interface Animal_interface_test04 {
//
void eat();
static void run(){
System.out.println("动物跑,这是静态方法");
}
}
class Dog_interface_test04 {
void eat(){
System.out.println("狗吃骨头,这是非静态方法");
}
}
抽象类和接口的区别
继承关系:抽象类使用extends关键字进行继承,而接口使用implements关键字进行实现。一个类只能继承一个抽象类,但可以实现多个接口。
实现方法:抽象类可以包含非抽象方法,也可以包含成员变量和构造函数,而接口只能包含抽象方法和常量(默认是public static final类型的)。因此,抽象类提供了部分实现,子类只需要实现抽象方法即可,而接口要求实现类提供完整的实现。
关系类型:抽象类是一种类的继承关系,用于表示类的共性特征,它不能被实例化。接口是一种更为抽象的规范,用于定义类应该具备的行为或功能,实现接口的类可以属于不同的继承关系。
代码示例:
public void test05() {
Bird_test05 bird = new Bird_test05();
bird.call();
bird.fly();
bird.sleep(); // 非静态方法可以直接被调用
// 输出:小鸟喳喳叫
// 小鸟嗷嗷飞
// 动物在睡觉
}
// 抽象类
abstract class Animal_test05 {
public abstract void call();
public void sleep() {
System.out.println("动物在睡觉");
}
}
//接口
interface Fly_test05{
void fly();
}
class Bird_test05 extends Animal_test05 implements Fly_test05{
@Override
public void call() {
System.out.println("小鸟喳喳叫");
}
@Override
public void fly() {
System.out.println("小鸟嗷嗷飞");
}
}
五、内部类
1.静态内部类(Static inner class)
定义在类的内部,并且被声明为static的内部类。
2.成员内部类(Member inner class)
定义在类的内部,且不是static的内部类。
3.本地内部类(Local inner class)
定义在方法内部的类,作用范围仅限于方法内部。
4.匿名内部类(Anonymous inner class)
没有名字的内部类,用于定义只使用一次的类。
public class OuterClass {
private int outerField;
// 成员内部类
public class MemberInnerClass {
public void innerMethod() {
System.out.println("Member Inner Class method");
}
}
// 局部内部类
public void localInnerClassMethod() {
class LocalInnerClass {
public void innerMethod() {
System.out.println("Local Inner Class method");
}
}
LocalInnerClass inner = new LocalInnerClass();
inner.innerMethod();
}
// 匿名内部类
public void anonymousInnerClassMethod() {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Anonymous Inner Class method");
}
};
Thread thread = new Thread(runnable);
thread.start();
}
// 静态内部类
public static class StaticInnerClass {
public void innerMethod() {
System.out.println("Static Inner Class method");
}
}
public static void main(String[] args) {
OuterClass outer = new OuterClass();
// 访问成员内部类
MemberInnerClass memberInner = outer.new MemberInnerClass();
memberInner.innerMethod();
// 访问局部内部类
outer.localInnerClassMethod();
// 访问匿名内部类
outer.anonymousInnerClassMethod();
// 访问静态内部类
StaticInnerClass staticInner = new StaticInnerClass();
staticInner.innerMethod();
}
}
六、Java Bean
Java Bean常用于封装数据,并提供公共的getter和setter方法来访问和修改数据。
代码示例:
public void test08() {
Animal_Bean cat = new Animal_Bean();
cat.set_Name("咪咪");
cat.set_Age(5);
Animal_Bean dog = new Animal_Bean();
dog.set_Name("旺财");
dog.set_Age(3);
System.out.println("小猫叫" + cat.get_Name() + ", 年龄" + cat.get_Age());
System.out.println("小狗叫" + dog.get_Name() + ", 年龄" + dog.get_Age());
}
// 输出:
// 小猫叫咪咪, 年龄5
// 小狗叫旺财, 年龄3
class Animal_Bean {
private String name;
private int age;
public Animal_Bean() {
// 无参构造函数
}
public String get_Name() {
return name;
}
public void set_Name(String name) {
this.name = name;
}
public int get_Age() {
return age;
}
public void set_Age(int age) {
this.age = age;
}
}