1.接口
使用interface关键字来定义接口,接口需要实现类来继承,使用关键字implements。
接口类的优点:
- 是一个特殊的抽象类
- 是一个引用数据类型(类,接口,数组)
- 实现解耦 耦合度
- 类只能单继承 ,接口多实现
- 更便于后期维护
- 定义开发规范
- 功能(抽象方法)的集合
值得注意的几点:
- 父类需要被子类继承 ,接口需要被类实现 implements
- 继承: 子类一旦继承父类,就可以直接使用父类的成员
- 实现: 接口中一般都是大量的抽象方法,必须要被实现,重写方法才可以使用,实现一个接口,需要重写抽象方法,侧重点在于实现
- 实现与继承非常像,实现也好,继承也好,都能够有权使用接口|父类中的成员|功能,但是侧重点不一样
- 接口中不能定义普通的方法,大部分为抽象方法
- 接口不能实例化
1.1jdk1.7版本及之前
接口内部定义公共的静态常量:
public static final 数据类型 常量名 = 赋值;
修饰符以任意省略 public、static、final
定义公共的抽象方法:
public abstract 返回值类型 方法名(参数列表);
同样修饰符可以任意省略 public、abstract
//接口InterfaceDemo继承了接口 In和In2
public abstract interface InterfaceDemo extends In,In2 {
double age = 18;
void a();
void b();
void c();
}
//接口In
abstract interface In{
void aa();
void bb();
void cc();
}
//接口In2
abstract interface In2{
void ab();
void ac();
}
//实现类
public class ImplementsTest implements InterfaceDemo {
@Override
public void a() {
System.out.println("a");
}
@Override
public void b() {
System.out.println("b");
}
@Override
public void c() {
System.out.println("c");
}
@Override
public void aa() {
System.out.println("aa");
}
@Override
public void bb() {
System.out.println("bb");
}
@Override
public void cc() {
System.out.println("cc");
}
@Override
public void ab() {
System.out.println("ab");
}
@Override
public void ac() {
System.out.println("ac");
}
}
//实现类 可以多实现
class Imple implements In,In2{
@Override
public void aa() {
}
@Override
public void bb() {
}
@Override
public void cc() {
}
@Override
public void ab() {
}
@Override
public void ac() {
}
}
1.2jdk1.8及之后
定义静态方法:
只能通过接口名使用,实现类对象不能使用;
默认方法:
通过实现类对象使用默认方法;
public interface InterfaceDemo03 {
//静态方法
public static void testStatic(){
System.out.println("接口中的静态方法");
}
//默认方法
default void testDefault(){
System.out.println("默认方法");
}
}
//实现类
class Impl implements InterfaceDemo03{
}
2.内部类
内部类是在类中定义类;当一个类中的成员,也是一个事物的时候,这个成员就可以定义为内部类。
内部类可以分为:
- 成员内部类
- 局部内部类
- 私有内部类
- 静态内部类
- 匿名内部类
2.1成员内部类
成员内部类有以下特点:
- 一个类作为另外一个类的成员
- 拥有成员与类的特性
- 成员内部类中不可以定义静态内容,除了静态常量
- 成员内部类中可以使用外部类中的所有成员,包括私有的
- 在外部类中通过内部类的对象使用内部类中的成员,包括私有的
- 其他类中使用成员内部类中的内容,需要通过外部类对象构建内部类对象,通过内部类对象使用内部类中的成员
public class Outer01 {
//成员
private int i = 1;
//成员内部类
public class Inner{
//成员变量
private String name = "成员内部类的name";
//静态的常量
static final int X= 123;
//成员方法
public void innerMethod(){
System.out.println("成员内部的成员方法");
System.out.println(X);
System.out.println(name);
System.out.println(i);
}
}
//外部类的方法
public void outerMehtod(){
System.out.println(Inner.X);
//内部类对象
Inner in = new Inner();
System.out.println(in.name);
}
}
2.2私有内部类
私有内部类即使用private 关键字修饰成员内部类,特点有以下:
-
在外部类中通过私有内部类的对象使用成员
-
在内部类中可以直接使用外部类中的成员,包含私有的
-
私有的内部类只能在当前的外部类中使用
public class Outer03 {
//成员
private int i = 1;
//私有内部类
private class Inner{
private String str = "私有内部类中的成员";
void testInner(){
System.out.println("私有内部类中的成员方法");
System.out.println(str);
System.out.println(i);
}
}
void testOuter(){
System.out.println("外部类的成员方法");
//通过内部类的对象使用内部 类中的成员,包含私有的
Inner in = new Inner();
in.testInner();
System.out.println(in.str);
}
}
2.3静态内部类
- 静态内部类中可以定义静态内容,其他成员成员内部类中不可以定义静态内容,除了静态的常量
- 静态内部类也是静态的内容,想要使用成员就需要通过对应类型的对象调用其成员
- 在其他类中使用静态内部类中的静态内容,通过外部类名.静态内部类名.静态内容
- 在其他类中使用静态内部类中的成员内容,通过new 外部类名.静态内部类名()的对象调用成员
public class Outer04 {
//成员变量
private int i = 1;
//静态变量
private static int j = 10;
//静态内部类
static class Inner{
int a = 5;
static int b = 15;
//成员方法
void test(){
System.out.println("静态内部类中的成员方法");
System.out.println(a);
System.out.println(b);
System.out.println(j);
System.out.println(new Outer04().i);
}
//静态方法
static void testStatic(){
System.out.println("静态内部类中的静态方法");
System.out.println(b);
//在静态内部类中的静态方法中,需要通过内部类对象使用成员
System.out.println(new Inner().a);
//在静态内部类中的静态方法中,需要通过外部类对象使用成员
System.out.println(new Outer04().i);
System.out.println(j);
}
}
}
2.4局部内部类
局部内部类定义在方法中,特点如下:
- 不能使用public,…static…修饰符修饰,final(太监类)可以
- 如果在局部内部类中使用当前中的局部变量,默认被final修饰(jdk8默认,jdk7及之前必须手动添加final)
- 局部内部类中的内容只有在当前方法中通过局部内部类的对象使用其成员
public class Outer05 {
void test(int args){
//局部
int i = 1;
//i = 1000;
//局部内部类
class Inner extends Object{
public int a = 5;
static final int b = 10; //静态常量
void test(){
System.out.println("局部内部类中的成员方法");
System.out.println(i);
System.out.println(args);
}
}
new Inner().test();
System.out.println( new Inner().a);
}
}
2.5匿名内部类(重点)
匿名内部类用于简化实现类或子类,因为接口或抽象类中可能存在抽象方法,必须在实现类或子类中重写,可以通过匿名内部类简化实现类或子类。
2.5.1匿名内部类对象创建
new 接口名|抽象类名(){
匿名内部类的类体;
}
以上创建的就是当前这个接口的实现类或这个抽象类的子类的对象。
public class Anonymous {
String name;
public static void main(String[] args) {
//匿名内部类的创建 {}中是Usb这个接口的实现类的方法重写
new Usb(){
@Override
public void play() {
System.out.println("玩");
}
@Override
public void sleep() {
System.out.println("睡觉");
}
}.sleep();//在结尾处直接引用重写的方法,这种创建匿名内部类对象的方式只能引用一种方法
//接口的引用指向实用类对象
Usb u = new Usb(){
@Override
public void play() {
System.out.println("玩");
}
@Override
public void sleep() {
System.out.println("睡觉");
}
};
u.play();//通过变量名直接应用重写方法
u.sleep();
//匿名内部类作为方法的参数
testUsb(new Usb(){//()中的内容相当于多态
@Override
public void play() {
System.out.println("玩");
}
@Override
public void sleep() {
System.out.println("睡觉");
}
});
}
public void other(){
}
static void testUsb(Usb usb){
usb.play();
}
interface Usb{
void play();
void sleep();
}
}
3.lambda表达式
jdk1.8新增的特性是lambda表达式,lambda表达式的目的是为了简化匿名内部类对象。
使用lambda表达式的前提是:函数式接口,其他的抽象类无法使用。
函数式接口:只有一个必须被重写的抽象方法的接口。
检查函数式接口的方式:@FunctionalInterface
lambda表达式的结构:
()- >{}
():重写的抽象方法的参数列表
->:箭头函数 lambda符号 具有上下文推导作用
{}:重写的抽象方法的方法体
public class LambdaDemo01 {
public static void main(String[] args) {
//lambda的接口简化匿名内部类对象的写法
//写法1.lambda写法1
Demo01 demo01 =()->{
System.out.println("哈哈哈笑");
};
//写法2.当抽象抽象方法的方法体语句只有一句的时候,前后的{}可以省略
Demo02 demo02 =()->System.out.println("哈哈哈笑");
//写法3.抽象方法有参数,参数的数据类型可以省略
Demo03 demo03 =(a,b)->System.out.println("哈哈哈笑");
//写法4.抽象方法的参数只有一个,前后的()可以省略
Demo04 demo04 =a->System.out.println("哈哈哈笑");
//写法5.抽象方法有返回值类型,方法的语句体只有一个,并且是return语句的时候,前后的{}与return关键字可以一起省略
Demo05 demo05 = a ->{
return "fanhuizhi";
};
Demo06 demo06 = a ->"fanhuizhi";
demo01.test();
demo02.test();
demo03.test(1,"1");
demo04.test(1);
System.out.println(demo05.test(1));
System.out.println(demo06.test(2));
}
}
interface Demo01{
void test();
}
interface Demo02{
void test();
}
interface Demo03{
void test(int a,String b);
}
interface Demo04{
void test(int a);
}
interface Demo05{
String test(int a);
}
interface Demo06{
String test(int a);
}