1.接口
接口格式:
权限修饰符(只有public和缺省的) interfa 接口名{
}
实现 类名 implement 接口名1 接口名2
类名实现接口名的方法时 不想实现的设置为抽象类 其余的都要实现
类与类只能单继承
接口与接口可以多继承
类与接口可以多实现
/*
接口:对不同类型不同事物相同功能的描述(一定程序上解决了单继承的局限性)
接口可以理解成一种标准 规范
当类实现这个接口就实现了这个标准或规范
接口的格式:
权限修饰符 interface 接口名{
}
权限修饰符只能是public和缺省的。
说明:
1.类和接口是并列的结构。
2.接口中有
JDK1.8之前 :常量,抽象方法
JDK1.8之后: 常量,抽象方法,静态方法,默认方法
3.接口不能实例化,接口中没有构造器。
4.接口和类的关系 :实现关系而且多实现
类名 implements 接口名1,接口名2,.......
5.当类实现接口后要实现接口中所有的抽象方法。如果不想实现该类可以声明为抽象类
6.接口和实现类的多态性 :接口的类型指向实现类的对象
7.接口和接口的关系 :继承关系并且是多继承
类和类的关系:单继承
类和接口的关系 :多实现
接口和接口的关系 :多继承
*/
interface A{
void showA();
}
interface B{
void showB();
}
interface C extends A,B{ //接口和接口是继承关系而且是多继承
}
abstract class Demo implements C{ //当类实现接口后要实现该接口中所有的抽象方法包括父接口中的-除非该类声明为抽象类
}
/*
接口
*/
interface MyInterface2{
void show();
}
/*
接口
*/
interface MyInterface{
//常量
public static final int ID = 10; //public static final 可以省略系统会默认加上
int AGE = 20;//public static final 可以省略系统会默认加上
//抽象方法
public abstract void say(); // public abstract 可以省略系统会默认加上
//void test();
}
class Person implements MyInterface,MyInterface2{
@Override
public void say() {
System.out.println("aaaa");
}
@Override
public void show() {
}
}
public class InterfaceTest {
public static final String PERSON_NAME = "龙哥";//常量
public static void main(String[] args) {
//调用接口中的抽象方法 : 实现类的对象.方法名
//调用接口中的常量 :接口名.常量名
System.out.println(MyInterface.ID);
new Person().say();
System.out.println("==========================");
test2(new Person());//实现类的对象 ==接口和实现类也可以实现多态 : 接口的类型 指向 实现类的对象
test3(new Person());//接口和实现类也可以实现多态 : 接口的类型 指向 实现类的对象
}
public static void test(Person p){
}
//接口和实现类也可以实现多态 : 接口的类型 指向 实现类的对象
//MyInterface mi = new Person();
public static void test2(MyInterface mi){//接口的类型
//向下转型
if (mi instanceof Person){
System.out.println("我是person");
}
}
public static void test3(MyInterface2 mi2){
}
}
1.多实现时的问题 —— 方法重复
实现时方法重复必须重写
重写时不能用defult(只能在接口中使用)
重写调用用super 接口名 。super。方法名
interface A{
static void run(){
System.out.println("A arun");
}
default void test(){
System.out.println("A test");
}
}
interface B{
static void run(){
System.out.println("B arun");
}
default void test(){
System.out.println("B test");
}
}
class SubClass implements A,B{
/*
当实现的多个接口中出了同名同参的默认方法时那么实现类必须重写此方法。
*/
@Override
public void test() { //重写接口中的默认方法时不要加default
//调用接口中被重写的方法 : 接口名.super.默认方法名
A.super.test();
B.super.test();
System.out.println("subClass test");
}
}
public class NewInterfaceTest2 {
public static void main(String[] args) {
new SubClass().test();
System.out.println("=======================");
//
}
}
2.接口的特性——实现多态
其中m是已经实现的接口(相当于子类),Computer。USB()中应填接口(相当于父类)’
构成将父类以子类的形式呈现 向下转型
/*
USB接口-标准 规范 约定
*/
interface USB{
void open();
void close();
}
interface Bluetooth{
void connect();
void disconnect();
}
/*
电脑
*/
class Computer{
public void runUSB(USB usb){
usb.open();
System.out.println("==================");
usb.close();
}
public void runBluetooth(Bluetooth b){
b.connect();
b.disconnect();
}
}
class Keyboard implements USB {
@Override
public void open() {
System.out.println("键盘灯亮起.....");
}
@Override
public void close() {
System.out.println("键盘灯熄灭");
}
}
/*
设备
*/
class Mouse implements USB,Bluetooth{
@Override
public void open() {
//驱动程序
System.out.println("鼠标的灯亮起来");
System.out.println("鼠标的指针闪起来");
System.out.println("请主人使用");
}
@Override
public void close() {
System.out.println("鼠标的灯全部熄灭");
System.out.println("主人你真的要那么做吗");
}
@Override
public void connect() {
System.out.println("鼠标蓝牙连接成功");
}
@Override
public void disconnect() {
System.out.println("鼠标蓝牙断开连接");
}
}
public class InterfaceTest2 {
public static void main(String[] args) {
//创建电脑对象
Computer c = new Computer();
//创建设备对象
Mouse m = new Mouse();
//将设备运行在电脑上
c.runUSB(m);//多态:接口和实现类的多态性
System.out.println("-------------------------");
Keyboard k = new Keyboard();
c.runUSB(k);
System.out.println("----------运行蓝牙设备--------------");
c.runBluetooth(m);
}
}
其中CRUDInterface 是被实现的接口 DAOClass是实现类
创建对象时相当于用实现类替代了被实现类 父类以子类形式实现 是向下转型
interface CRUDInterface{
void insert(int id,String name);
void update(int id,String ... value);
void delete(int id);
}
/*
伟哥 : 要操作数据库
*/
class DAOClass implements CRUDInterface{
@Override
public void insert(int id, String name) {
//创建Connection对象
//写sql语句
//运行sql语句
//查看运行结果
System.out.println("插入数据" + id + " " + name);
}
@Override
public void update(int id, String... value) {
}
@Override
public void delete(int id) {
//创建Connection对象
//写sql语句
//运行sql语句
//查看运行结果
System.out.println("删除数据" + id);
}
}
/*
小龙哥
该类和页面发过来的数据交互 然后调用后面具体的操作
*/
class VClass{
//多态
CRUDInterface c = new DAOClass(); //接口
//接收到页面发过来的删除请求
public void delete(int id){
//判断
//和页面交互 询问是否删除
//判断
if (true){
//调用其它类中的删除数据库中数据方法
c.delete(id);
}else{
//直接跳转到其它页面
}
}
}
public class InterfaceTest3 {
public static void main(String[] args) {
new VClass().delete(1);
}
}
3.接口的补充——静态方法和默认方法
静态方法用static修饰
默认方法用defaul修饰
优先原则:继承父类优先于实现接口类
/*
JDK1.8开始 接口中增加了静态方法和默认方法
说明:
1.接口中的静态方法的调用 : 接口名.静态方法名
2.接口中的默认方法的调用 : 实现类的对象.默认方法名
3.类优先原则 :当父类和接口中的默认方法出现了同名同参的那么默认调用父类中的该方法。
4.接口冲突 : 当实现的多个接口中出了同名同参的默认方法时那么实现类必须重写此方法。
5.在实现类的重写方法中调用接口中被重写的方法 : 接口名.super.默认方法名
JDK1.9开始 :接口中增加私有方法(方法被private修饰)--知道即可
注意:
在类中重写接口中的默认方法不要加default
*/
interface MyInterface{
int ID = 5;
//void test();
//静态方法
static void show(){ //必须是public - public可以省略不写
System.out.println("show");
}
//默认方法
default void run(){ //类似于实例方法 //必须是public - public可以省略不写
System.out.println("run");
}
}
class SuperClass{
public void run(){
System.out.println("superClass run");
}
}
class MyClass extends SuperClass implements MyInterface{
}
public class NewInterfaceTest {
public static void main(String[] args) {
//调用接口中的静态方法
MyInterface.show();
//调用接口中的默认方法
MyClass mc = new MyClass();
mc.run();//亲爹优先原则(类优先原则)
}
}
4.instanof 在接口中的应用
左边的是继承后实现的类
右边是被实现类及其父类
实现类可视为被被实现类包含
package com.atguigu.java3;
interface A{
}
interface B extends A {
}
interface C extends B{
}
class SubClass implements C{
}
public class InterfaceTest {
public static void main(String[] args) {
SubClass sb = new SubClass();
System.out.println(sb instanceof C);
System.out.println(sb instanceof B);
System.out.println(sb instanceof A);
}
}
2.内部类
1.内部类介绍
内部类可以被四种权限修饰符修饰
内部类可调用外部类 外部类则不可以调用内部类
内部类的调用 变量名:调用内部类中的变量
this + 变量名: 调用外部类中内部类外变量
类名。this。变量名 : 调用外部类中私有变量
非静态成员内部类中不能声明类变量和类方法 因为类是非静态的
内部类继承其他类来实现多继承的效果
内部类可以实现类的高内聚低偶和(即本类内东西自己调用,减少与其他类的交际)
/*
类的成员之内部类
内部类:在一个类A的内部再定义一个类B。类B叫作内部类,类A叫作外部类。
内部类的作用:
1.内部类可以很好的实现类的隐藏。
2.可以实现多继承的效果。
3.可以很好的实现高内聚低偶合
内部类的分类
成员内部类 :位置在类中其它结构外
静态成员内部类:
非静态成员内部类:
局部内部类
普通局部内部类
匿名局部内部类
说明:
1.内部类可以被四种权限修饰符修饰。外部类只能被public和缺省的修饰
2.内部类可以调用外部类私有的成员。外部类不能调用内部类私有的成员。
3. 创建非静态成员内部类的对象:外部类的对象.new 非静态成员内部类名();
创建静态成员内部类的对象 : new 外部类名.静态成员内部类类名();
4.在非静态成员内部类调用外部类的成员(属性和方法) :外部类名.this.属性名/方法名
在静态成员内部类调用外部类的成员(只能调用静态的) : 外部类名.类变量名/类方法名
5.在非静态成员内部类中不能声明类变量和类方法 - 因为类是非静态的(类的成员)
*/
class Person{
private int pid = 10;
static int sid = 10;
/*
非静态成员内部类
*/
class Heart{
int pid = 20;
//外部类无法调用内部类中的私有的成员
private void test(){
System.out.println("heart private test");
}
/*
在非静态成员内部类中不能声明类变量和类方法 - 因为类是非静态的(类的成员)
public static void demo(){
}
*/
public void show(){
int pid = 30;
System.out.println("heart show");
System.out.println(pid);//就近原则-局部变量
System.out.println(this.pid);//调用的是本类中的属性
System.out.println(Person.this.pid);//内部类可以调用外部类私有的成员
}
}
/*
静态成员内部类
*/
static class Liver{ //静态的只能调用静态的
public void show(){
System.out.println("liver show");
System.out.println(Person.sid);//调用外部类的类变量 : 外部类名.类变量名
}
}
public void show(){
//普通局部内部类
class A{
}
}
}
public class InnerClassTest {
public static void main(String[] args) {
//创建外部类的对象
Person p = new Person();
//创建非静态成员内部类的对象:外部类的对象.new 非静态成员内部类名();
//持有外部类的引用-只要非静态成员内部类的对象不被GC掉那么外部类的对象将永远无法被GC(垃圾回收器回收)-造成内存泄露
Person.Heart heart = p.new Heart();
heart.show();
System.out.println("===========================================");
//创建静态成员内部类的对象 : new 外部类名.静态成员内部类类名();
Person.Liver liver = new Person.Liver();//老高认为静态成员内部类就不是内部类
liver.show();
}
}
2.普通内部类
普通局部内部类(方法中创建类)
/*
局部内部类: 普通局部内部类 vs 匿名局部内部类
*/
class SuperA{
public void show(){
System.out.println("superA show");
}
}
class Animal{
public void eat(){
//普通局部内部类
class A{
public void show(){
System.out.println("show");
}
}
new A().show();
}
/*
通过方法获取普通局部内部类的对象
1.让局部内部类实现或继承外部的某一个类或某一个接口(要有方法的重写要不然没意义)。
2.方法的返回值类型就是继承的类或实现的接口的类型。
3.调用方法获取返回值-只能用继承的类或实现的接口的类型接收(多态)。
4.不能向下转型-因为在类的外部类根本就不识别局部内部类的类型。
注意:局部内部类不能被权限修饰符修饰 - 因为作用域的原因(就在那对大括号里)
*/
public SuperA getA(){ //返回值类型不能是内部类的类型 - 不认识(作用域)
int id;//局部变量不能使用权限修饰符
//普通局部内部类
class A extends SuperA{
@Override
public void show(){
System.out.println("a show");
}
}
return new A(); //多态
}
}
public class InnerClassTest2 {
public static void main(String[] args) {
new Animal().eat();
//获取局部内部类的对象
Animal a = new Animal();
SuperA a1 = a.getA();//多态
//可以向下转型吗?不可以 - 不认识
a1.show();
}
}
3.匿名内部类
new 抽象类 {重写}
普通要写名字 写继承 重写
匿名类则 new抽象类 或接口 {重写}即可
匿名类算继承或实现后的对象而非匿名类或抽象类
/*
匿名局部内部类
格式:
new 接口名/抽象类名/类名([形参列表]){
重写方法/实现方法
};
*/
import java.util.Collections;
import java.util.function.Supplier;
import java.util.stream.Stream;
interface Computer{
void show();
}
abstract class Demo{
public abstract void run();
}
class A2{
public void run(){
}
}
public class InnerClassTest3 {
public static void main(String[] args) {
//该类只是自己用而且只用一次 - 局部内部类
class A implements Computer{
@Override
public void show() {
System.out.println("A show");
}
}
//创建匿名内部类的对象
/*
Computer c = new Computer() { //创建的是Computer接口的实现类的对象-只不过该类没有名字
@Override
public void show() {
System.out.println("匿名内部类的对象");
}
};
*/
run(new Computer() { //最最最最最常见 --创建的是匿名内部类(该类只用一次而且没有名字)的匿名对象
@Override
public void show() {
System.out.println("大哥是匿名内部类的匿名对象");
}
});//实参得是接口的实现类的对象
System.out.println("============================================");
//抽象类 - 创建匿名内部类的对象 - Demo类的子类的对象。
Demo demo = new Demo(){
@Override
public void run() {
}
};
System.out.println("============================================");
//普通类 - 创建匿名内部类的对象 - A2类的子类的对象。
A2 a2 = new A2() {
@Override
public void run() {
}
};
}
public static void run(Computer c){
c.show();
}
}