【Java】对象、类(抽象类与内部类)、接口
博文内容概况
对象是对客观事物的抽象,类是对对象的抽象。类是一种数据类型,其外观和行为由用户定义。类中可以设置两种类型的元素:字段(有时被称为数据成员)和方法(有时被称为成员函数)。字段可以是任何类型的对象。如果类的某个成员是基本数据类型,即使没有进行初始化,Java也会给它一个默认值,但用户最好自行对其进行初始化。
基本类型 | 默认值 |
boolean | false |
char | '\u0000'(null) |
byte | (byte)0 |
short | (short)0 |
int | 0 |
long | 0L |
float | 0.0f |
double | 0.0d |
/** 1. 被abstract修饰的类即为抽象类;包含一个或多个抽象方法的即为抽象类 2. 抽象类的权限修饰符为public,缺省(如下)也为public; 3. 抽象类无法创建对象(即不能new); 4. 其余情况与普通类相同。 */ abstract class animal { int num;//成员变量可使用任何访问权限修饰词(public、protected、private) /** 1. 抽象方法必须为public或protected,缺省即为public; 2. 抽象方法没有方法体,即符号{}; 3. 子类中必须实现抽象方法,否则子类仍为抽象类。 */ abstract void run(); } class lion extends animal{ void run(){} }
interface提供一个完全抽象的类,没有提供任何具体实现。它允许创建者确定方法名、参数列表和返回类型。
/** 在Java8版本中,接口的功能增强了,接口中允许存在: 1. 变量 - 必须为public static final形式的变量; 2. 抽象方法 - public abstract关键词在接口中可省略; 3. 具体方法 - 以static、default关键词修饰的方法,关键词不可省略(Java8新增的内容) * 方法默认的权限为public */ public interface animal { public static final int a = 8; //static方法 static void staticMethod() { System.out.println("---animal static method---"); } //default方法 default void defaultMethod() { System.out.println("---animal default method---"); } //抽象方法 void run(); }
调用static、default方法如下
class lion implements animal { public static void main(String[] args) { //调用接口中的静态方法——接口名.静态方法名(与调用普通类的静态方法一样) animal.staticMethod(); //调用接口中的default方法 实现接口并实例化该实现类 lion l = new lion(); l.defaultMethod(); } @Override public void run() {} }
总结,抽象类和接口之间的异同
(√表示允许存在,×表示不存在)
抽象类 | 接口 | |
定义(关键词) | abstract class | interface |
类的权限修饰符 | public与缺省相同 | public、缺省 |
变量 | 没有任何限制 | 必须以public static final修饰 |
抽象方法 | √ | √ |
抽象方法权限修饰符 | public、protected、缺省(default)[1.8] | 缺省默认为public |
构造方法 | √ | × |
普通方法 | √ | √[1.8] |
静态方法 | √ | √[1.8] |
静态块 | √ | × |
继承方式 |
子类只能继承1个抽象类 抽象类可以继承一个类(抽象类、实体类均可)和实现多个接口 (extends、implements)* |
接口可以继承多个接口 子类可以实现多个接口 (implements)** |
作用 | 重用 | 降低耦合 |
*子类继承抽象类时需要重写父类所有的抽象方法,可以实例化;若不能完全重写,则该子类仍为抽象类;
**子类实现接口时需要实现全部的抽象方法,否则该子类为抽象类。
·成员内部类
public class Outer { private int num = 8; private int out = 10; private Inner in = null; public Outer() { in = new Inner(); } //内部类的访问权限-public、protected(外部类的子孙类可访问)、默认(与外部类同包)、private(只能在外部类内部访问) public class Inner{ private int out; public void doSomething() { //内部类可直接访问外部类的成员 System.out.println(num); //当内部类拥有外部类同名的成员变量和方法,需要通过[外部类.this.成员变量/成员方法] 进行访问 System.out.println(Outer.this.out); } } public static void main(String[] args) { //成员内部类依靠外部类存在,所以访问内部类时需要一个外部类的对象 Outer.Inner inner = new Outer().new Inner(); inner.doSomething();//访问内部类成员方法 inner.out++;//访问内部类成员变量 } }
·静态内部类
public class Outer { int a; static int b; static class Inner{ public Inner() { //System.out.println(a); 编译不通过 System.out.println(b);//只能访问外部的静态变量 } } }
·局部内部类
public class Outer { public int out; public static int out_s; public void method() { int num; class Inner{ //num++; 编译不通过,无法使用可变的局部变量 public void print() { System.out.println(out++);//可以使用外部类的成员变量 } } } static void method2() { class Inner{ public void print() { System.out.println(out_s++);//static方法中的内部类只能使用静态变量 } } } }
·匿名内部类
/** 1. 匿名内部类是唯一没有构造器的类,用于继承其他类、实现接口; 2. 匿名内部类的好处是使用便捷 3. 通过实例初始化,达到匿名内部类创建一个构造器的效果 如例,Thread()中的部分为Thread的内部类,通过实例(new)Runnable接口达到想要的效果 */ Thread t = new Thread(new Runnable() { @Override public void run() { for(int i=0;i<100;i++) { System.out.println(Thread.currentThread().getName()+i); } } }); t.start();
成员内部类 | 静态内部类 | 局部内部类 | 匿名内部类 | |
权限 |
package,public,protected,
private
|
不允许有public、protected、private、static | 不能有访问修饰符 | |
修饰词 | 成员内部类可看作外部类的一个成员,所以可以像成员一样拥有多个权限修饰词 | static(必须) | 可以使用final/abstract | 不能有static |
定义位置 |
在另一个类的内部,
与成员方法、属性平级
|
定义在方法、代码块、
作用域({}中)
|
||
访问内部 | 通过内部类的实例访问 | |||
访问外部 | (内外部成员名字相同时)外部类.this.成员变量 |
只能访问静态成员(
变量/方法)
|
||
特点 | 无需依赖外部类 | 只能使用一次 |
参考:
《Java编程思想》
https://www.cnblogs.com/dolphin0520/p/3811445.html(海子:Java内部类详解)