abstract
- 抽象类可以有构造器,便于子类调用
- 抽象类:不能实例化。例如
//按照原始的写法,定义一个类
public class Person{
String name;
int age;
public Person(){ //构造方法
}
}
//对该类实例化操作
Person person = new Person(); //该实例化可以操作
//下面定义一个 抽象类:含有abstract的关键字
public abstract class Person{
String name;
int age;
public Person(){ //构造方法
}
}
//对该抽象类进行实例化
Person person = new Person(); //error.即不允许实例化
- 抽象方法:
①包含抽象方法的类一定是个抽象类。
②抽象类不一定含有抽象方法。如上一个例子就没有抽象方法
//抽象类
abstract class Person{
String name;
int age;
public Person(){
}
abstract void eat(); //抽象方法,只有方法名,没有方法体
}
//现在编写一个子类让他继承Person类。
//对于子类有两种处理方式:
// ①让子类继承超类所有抽象方法
// ②子类也是个抽象类
// 例子如下:
//①子类继承超类所有抽象方法
class Student extends Person {
@Override
void eat() {
}
}
//②子类也是个抽象类
abstract class Student extends Person {
}
//abstract 不能修饰私有、静态、final方法、final的类
abstract不能被static,final,private修饰
非抽象子类继承抽象类,要重写所有的抽象方法
①被final修饰的方法不能被重写
②被private修饰的方法只能本类使用
③被static修饰的方法并不能被重写
Java是单继承,不能多继承,所以引出接口的概念
接口
- 接口所有方法必须是
public abstract
,可省略。但是在实现接口时,方法的修饰符必须是public
的,不能省略。
//定义一个接口
interface Fly{
public abstract void eat(); //标准写法
void work(); //省略了public abstract
}
- 接口不能含有构造器,接口不能含有实例域,接口也不能实例化
- 接口中可以含有常量,格式是
public static final int x
;其中public static final
可以省略
//定义一个接口
interface Fly{
//接口中 常量必须 初始化,且初始化后不可修改
//int NUM_A = 3; //可以省略public static final
public static final int NUM_A = 3; //标准写法
}
- 接口与接口之间可以多继承
interface A{
}
interface B{
}
interface C extends A,B{
}
- 接口的匿名实现类
//定义USB接口
interface USB{
void inputInofo();
void outputInfo();
}
//USB接口的实现类
class Computer implements USB{
public void inputInofo() {
System.out.println("MyComputer输入信息[^L^]。。。。。。");
}
public void outputInfo() {
System.out.println("MyComputer输出信息[^_^]。。。。。。");
}
}
public class mainTest {
public void streamData(USB usbImpl){
usbImpl.inputInofo();
usbImpl.outputInfo();
}
@Test
public void test1(){
//1.非匿名实现类的非匿名对象
Computer computer = new Computer(); // ==> USB usbImpl = new Computer();
streamData(computer);
}
@Test
public void test2(){
//2.非匿名实现类的匿名对象
streamData(new Computer());
}
@Test
public void test3(){
//3.匿名实现类的非匿名对象
USB usbImpl = new USB() {
public void inputInofo() {
System.out.println("[匿名实现类,非匿名对象]输入。。。。");
}
public void outputInfo() {
System.out.println("[匿名实现类,非匿名对象]输出。。。。");
}
};
streamData(usbImpl);
}
@Test
public void test4(){
//4.匿名实现类的匿名对象
new USB() {
public void inputInofo() {
System.out.println("[匿名实现类,匿名对象]输入。。。。");
}
public void outputInfo() {
System.out.println("[匿名实现类,匿名对象]输出。。。。");
}
};
}
}
- jdk8之后在接口里可以定义静态方法和默认方法。
①接口中的静态方法只能自己调用。即接口.静态方法。
②可以重写接口的方法。
定义一个接口Named,里面有静态方法和默认方法
public interface Named {
public static void mehtod1(){
System.out.println("接口方法1");
}
public default void mehtod2(){
System.out.println("接口方法2");
}
}
定义一个LiMing类实现Named接口,同时测试一下
public class Student {
public static void main(String[] args) {
LiMing liMing = new LiMing();
liMing.mehtod2();
Named.mehtod1();
}
}
class LiMing implements Named{
}
结果如下:
接口方法2
接口方法1
可以重写接口的默认方法,如下:
public class Student {
public static void main(String[] args) {
LiMing liMing = new LiMing();
liMing.mehtod2();
Named.mehtod1();
}
}
class LiMing implements Named{
public void mehtod2(){
System.out.println("接口方法2被重写");
}
}
结果如下:
接口方法2被重写
接口方法1
默认方法的冲突
- 超类优先:如果超类提供了一个具体方法, 同名而且有相同参数类型的默认方法会
被忽略。
定义接口A
public interface A {
public default void xx(){
System.out.println("接口A 中 xx方法");
}
}
编写父类B
public class B {
public void xx(){
System.out.println("类B 中 xx方法");
}
}
编写子类C让其继承B实现A接口
public class C extends B implements A{
}
编写测试类:
public class TestABC {
public static void main(String[] args) {
C c = new C();
c.xx();
}
}
结果如下:
类B 中 xx方法
- 接口冲突: 如果一个超接口提供了一个默认方法, 另一个接口提供了一个同名而且
参数类型 (不论是否是默认参数)相同的方法, 必须覆盖这个方法来解决冲突。
编写接口D
public interface D {
public default void xx(){
System.out.println("接口D 中 xx方法");
}
}
编写类C,让他实现接口A和D,则必须重写方法XX()
public class C implements A,D{
@Override
public void xx() {
System.out.println("实现方法");
}
}
编写测试类:
public class TestABCD {
public static void main(String[] args) {
C c = new C();
c.xx();
}
}
结果:
实现方法
2.内部类
- 成员内部类(定义在一个类中,方法外)
① 作为一个类:可以定义方法,属性,构造器等。可以用final修饰。可以用abstract修饰。
② 作为一个外部成员:可以被static修饰(普通类是不能被static修饰的),可以被四种修饰符修饰,可以调用外部类的结构
//定义一个Animal类:理解成员内部类
class Animal{
String name;
int age;
public void name(){
System.out.println("孟子");
}
//静态成员内部类
static class Bird{
String name;
int age;
public Bird(){
}
public void eat(){
System.out.println("鸟吃饭");
}
}
//非静态成员内部类
class Cat{
String name;
int age;
public void eat(){
System.out.println("猫吃饭");
}
}
}
//成员内部类的实例化问题
public static void main(String[] args) {
//1. 非静态 实例化
Animal animal = new Animal();
Animal.Cat cat = animal.new Cat();
cat.eat()
//2. 静态 实例化
Animal.Bird bird = new Animal.Bird();
bird.eat();
}
/**
输出结果:
猫吃饭
鸟吃饭
*/
//非静态 成员内部类调用方法
//在Cat类中添加show方法
public void show(){
name();
Animal.this.name(); //和name()效果一样
}
//测试
Animal animal = new Animal();
Animal.Cat cat = animal.new Cat();
cat.show();
//结果:
//孟子
//孟子
- 局部内部类(定义在代码块内,方法内,构造器内等)
局部类不能用 public 或 private 访问说明符进行声明。它的作用域被限定在声明这个局部类的块中。局部类有一个优势, 即对外部世界可以完全地隐藏起来。