一、接口
(一)接口的概述
1、广义:一切定义规则的事物都是接口
2、狭义:Java中用于定义方法声明的规则就是接口,Java的接口中,定义的所有方法都是抽象方法
3、好处:将方法的调用和方法的实现分离开了,可以降低代码的耦合度,可以提升开发的效率
(二)接口的特点
1、定义格式:使用关键字interface声明,一个接口编译过后也会生成一个独立的.class文件
interface 接口名 {
}
2、接口中,只能声明定义抽象方法,不能定义有方法实现的方法
3、接口的实现:使用类,通过implements关键字来实现接口
(1)格式:class 类名 implements 接口名 {}
(2)接口中只有规则没有实现,我们通过类来去添加规则的实现,不同的类可以实现相同的接口,给予接口不同的实现
4、接口不能实例化,不能创建对象
我们是用接口的时候是通过类来实现接口的,类可以创建对象,将来通过创建接口的实现类的对象,对象来调用实现了的方法
5、接口实现类的前途:
(1)当接口的实现类实现了接口中所有的抽象方法,这个类就是一个普通类,可以创建对象调用方法
(2)当接口的实现类没有完全实现接口的抽象方法,这个类就是一个抽象类,就需要抽象类的子类进一步实现剩余的抽象方法,知道实现子类变成普通类
代码示例
public class Demo01_Interface {
public static void main(String[] args) {
//MyInter1 mi = new MyInter1();
/*Inter1 i1 = new Inter1();
i1.test1();
Inter2 i2 = new Inter2();
i2.test1();*/
//接口的引用指向实现了的对象
MyInter1 my1 = new Inter1Zi();
MyInter1 my2 = new Inter2();
my1.test1();
my2.test1();
}
}
/*
* interface 接口名 {
}
*/
interface MyInter1 {
public abstract void test1();
public abstract void test2();
}
abstract class Inter1 implements MyInter1 {
@Override
public void test1() {
System.out.println("Inter1实现了接口");
}
}
class Inter1Zi extends Inter1 {
@Override
public void test2() {
}
public void show() {
System.out.println("!!!!!!!1");
}
}
class Inter2 implements MyInter1 {
@Override
public void test1() {
System.out.println("Inter2实现了接口");
}
@Override
public void test2() {
}
}
(三)接口中成员的特点
1、成员变量:没有!接口中只能定义常量不能定义变量!当我们定义一个常量时,会默认加上public static final,建议手动加上
2、构造方法:没有!因为接口中没有成员变量,没有需要赋值的部分,所以接口没有构造方法
3、成员方法:只能是抽象方法,不能是非抽象方法。方法的声明可以省略public abstract,建议手动加上
代码示例
public class Demo02_InnerInterface {
public static void main(String[] args) {
}
}
interface MyInter2 {
public static final int num = 10;//常量
public abstract void test();
}
class Inter3 {
void test() {
}
}
(四)类与类、类与接口、接口与接口之间的关系
1、类与类:继承关系,使用extends关键字。支持单继承,不支持多继承,支持多层继承
2、类与接口:实现关系,使用implements关键字。
(1)支持单实现,支持多实现。不存在多层实现(接口一旦被类实现,就变成了类与类的关系)
(2)单实现:
class 类名 implements 接口名 {
实现接口中所有的抽象方法
}
(3)多实现:
class 类名 implements 接口1, 接口2, 接口3, …, 接口n {
实现接口中所有的抽象方法
}
此格式不存在安全隐患。就算多个接口中有同名方法,但是在同一个实现类中,能对 应到的方法体只有一个,不会和别的方法体起冲突,所以没有安全隐患。
(4)一个类在实现多个接口的同时还能继承一个类:
class 子类类名 extends 父类类名 implements 接口1, 接口2, 接口3, …, 接口n {
实现接口中所有的抽象方法
重写父类中继承来的方法
}
3、接口与接口:继承关系,使用extends关键字(类相当于是亲爹,接口相当于是干爹)
(1)支持单继承,支持多继承,支持多层继承
(2)接口的多继承格式:
interface 接口1 extends 接口1, 接口2, 接口3, …, 接口n {
相当于整合了声明上所有接口的抽象方法
}
4、设计思路:
(1)类一般用于定义事物固有的属性和行为
(2)接口一般用于定义事物通过扩展或者学习得来的功能
代码示例
public class Demo03_ClassAndInterface {
}
interface MyInter10 {
public abstract void test1();
}
interface MyInter11 extends MyInter10 {
public abstract void test2();
}
interface MyInter12 extends MyInter11, MyInter10 {
public abstract void test3();
}
/*class Inter5 implements MyInter12 {
@Override
public void test2() {
}
@Override
public void test1() {
}
@Override
public void test3() {
}
}*/
interface MyInter3 {
public abstract void test1();
public abstract void test2();
}
interface MyInter4 {
public abstract void test3();
}
interface MyInter5 {
public abstract void test4();
public abstract void test1();
public abstract void test2();
}
class Father {
private int num;
private String str;
private double dou;
public Father() {
super();
}
public Father(int num, String str, double dou) {
super();
this.num = num;
this.str = str;
this.dou = dou;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public double getDou() {
return dou;
}
public void setDou(double dou) {
this.dou = dou;
}
}
class Inter4 extends Father implements MyInter3, MyInter4, MyInter5 {
@Override
public void test4() {
}
@Override
public void test3() {
}
@Override
public void test1() {
System.out.println(getDou());
System.out.println(getNum());
System.out.println(getStr());
}
@Override
public void test2() {
}
}
(五)案例1:会跳高的猫
设计: 动物类:姓名,年龄,吃饭,睡觉。 猫类(捉老鼠) 狗类(看家)
设计一个动物培训接口,可以培训跳高
会跳高的猫类(跳高)
合理设计代码,需要使用到封装、继承、多态、抽象
代码示例
/**
* 2、设计: 动物类:姓名,年龄,吃饭,睡觉。 猫 类(捉老鼠) 狗类(看家)
* 设计一个动物培训接口,可以培训跳高
* 会跳高的猫类(跳高)
* 合理设计代码,需要使用到封装、继承、多态、抽象
*
* @author Zihuatanejo
*
*/
public class Demo04_Homework02 {
public static void main(String[] args) {
Animal a = new JumpingCat();
a.eat();
a.sleep();
Cat c = (Cat)a;
c.catchMouse();
JumpingCat jc = (JumpingCat)c;
jc.jump();
}
}
/**
* 动物类
*
* 姓名,年龄,吃饭,睡觉
*
* @author Zihuatanejo
*
*/
abstract class Animal {
private String name;
private int age;
public Animal() {
super();
}
public Animal(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public abstract void eat();
public abstract void sleep();
}
/**
* 猫类(捉老鼠)
*
* @author Zihuatanejo
*
*/
class Cat extends Animal {
public Cat() {
super();
}
public Cat(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("吃鱼");
}
@Override
public void sleep() {
System.out.println("在树上睡觉");
}
public void catchMouse() {
System.out.println("捉老鼠");
}
}
/**
* 狗类(看家)
*
* @author Zihuatanejo
*
*/
class Dog extends Animal {
public Dog() {
super();
}
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("吃骨头");
}
@Override
public void sleep() {
System.out.println("趴在地上睡");
}
}
interface Jumping {
public abstract void jump();
}
class JumpingCat extends Cat implements Jumping {
public JumpingCat() {
super();
}
public JumpingCat(String name, int age) {
super(name, age);
}
@Override
public void jump() {
System.out.println("猫跳高");
}
}
(六)电脑USB案例
定义一个电脑类型(Computer),要求:开机方法(powerOn)、关机方法(powerOff),并且还有一个使用USB接口的方法,例如接入键盘,让键盘输入,接入鼠标,让鼠标点击
合理设计代码,创建电脑对象,让电脑开机,使用USB接口接入外设,让外设运行,让电脑关机
代码示例
/**
* 定义一个电脑类型(Computer),要求:开机方法 (powerOn)、关机方法(powerOff),
* 并且还有一个使用USB接口的方法,例如接入键盘,让键盘输入,接入鼠标,让鼠标点击
合理设计代码,创建电脑对象,让电脑开机,使用USB接口接入外设,让外设运行,让电脑关机
*
* @author Zihuatanejo
*
*/
public class Demo05_USB {
public static void main(String[] args) {
Computer c = new Computer();
c.powerOn();
USB k = new Keyboard();
USB m = new Mouse();
c.useUSB(k);
c.useUSB(m);
c.powerOff();
}
}
class Computer {
public void powerOn() {
System.out.println("电脑开机");
}
public void useUSB(USB usb) {//USB usb = new Keyboard();
usb.run();
}
public void powerOff() {
System.out.println("电脑关机");
}
}
interface USB {
public abstract void run();
}
class Keyboard implements USB {
@Override
public void run() {
System.out.println("键盘录入");
}
}
class Mouse implements USB {
@Override
public void run() {
System.out.println("鼠标点击");
}
}
二、内部类
(一)内部类的概述
1、定义在类的内部的类,就是内部类。和方法、变量等,均作为类的成员。
2、根据定义位置的不同,可以分为:
(1)成员内部类
(2)局部内部类
3、成员内部类:
(1)普通成员内部类
(2)私有成员内部类
(3)静态成员内部类
4、局部内部类
5、根据表示方式的不同:
(1)有名字的内部类
(2)匿名内部类
(二)普通成员内部类
1、定义在类成员位置的类,就是成员内部类
2、格式:
class 外部类类名 {
外部类成员
class 内部类类名 {
内部类成员
}
}
3、成员内部类的说明:
(1)内部类可以直接访问外部类中所有的成员
(2)外部类中,不能直接访问内部类的成员,必须通过在外部类中创建内部类的对象,方可访问
(3)在外部类以外访问内部类的成员,可以创建外部类对象,对象调用外部类方法,方法中通过内部类对象访问内部类成员,从而达成间接访问
(4)在外部类以外访问内部类的成员,可以直接创建内部类对象:
外部类名.内部类名 对象名 = new 外部类名().new 内部类名();
代码示例
public class Demo06_InnerClass {
public static void main(String[] args) {
/*System.out.println(new Body1().age);
Body1 b = new Body1();
b.test();*/
//外部类名.内部类名 对象名 = new 外部类名().new 内部类名();
Body1.Heart bh = new Body1().new Heart();
System.out.println(bh.color);
}
}
class Body1 {
private int length = 175;
int age = 10;
class Heart {
String color = "黑色";
private int weight = 80;
public void show() {
System.out.println(age);
System.out.println(length);
}
}
Heart h = new Heart();
public void test() {
System.out.println(age);
System.out.println(h.color);
System.out.println(h.weight);
}
}
(三)私有成员内部类
1、在普通成员内部类的声明上加上private关键字
2、格式:
class 外部类类名 {
外部类成员
private class 内部类类名 {
内部类成员
}
}
3、私有成员内部类的说明:
(1)在私有成员内部类中,可以访问所在外部类的所有成员
(2)在外部类中,要通过内部类对象访问内部类成员
(3)在外部类以外,只能通过间接方式访问私有成员内部类的内容。没有任何的直接访问方式。因为对于外部类而言,私有成员内部类也是一个私有成员,所以在外界无法直接访问。
代码示例
public class Demo07_PrivateInnerClass {
public static void main(String[] args) {
Body2 b = new Body2();
b.test();
}
}
class Body2 {
private String name = "张三";
int age = 23;
private class Liver {
String color = "黑色";
private int height = 171;
public void show() {
System.out.println(name);
System.out.println(age);
}
}
Liver l = new Liver();
public void test() {
System.out.println(l.color);
System.out.println(l.height);
}
}
(四)静态成员内部类
1、格式:
class 外部类类名 {
外部类成员
static class 内部类类名 {
内部类成员
}
}
2、访问特点:
(1)静态成员内部类是外部类的静态成员
(2)在静态成员内部类中,访问外部类成员,外部类成员如果是静态的就按照静态访问,非静态就按照非静态访问
(3)在外部类中,访问静态成员内部类的内容,也要按照静态按照静态访问,非静态按照非静态访问
(4)总结:访问的内容,到底用静态方式还是非静态方式,不取决于类本身是否为静态,而是取决于要访问的内容本身是静态还是非静态
(5)在外部类以外创建静态成员内部类的格式:
外部类名.内部类名 对象名 = new 外部类名.内部类名();
代码示例
public class Demo08_StaticInnerClass {
public static void main(String[] args) {
Body3.Lung bl = new Body3.Lung();
bl.show();
}
}
//1.对于外部类而言,内部类是一个静态的成员
//2.静态成员内部类访问外部类的静态成分是可以直接访问的
//3.静态成员内部类无法直接访问外部类的非静态成员
//4.在静态成员内部类中访问外部类的非静态成员需要通过外部类对象来访问
class Body3 {
static int num = 10;
String name = "张三";
static class Lung {
String color = "黑色";
static int length = 159;
//Body3 b = new Body3();
public void show() {
System.out.println(num);
//System.out.println(b.name);
}
}
Lung l = new Lung();
public void test() {
System.out.println(Lung.length);
System.out.println(l.color);
}
}
(五)局部内部类
1、局部内部类:定义在方法中的类
2、访问说明:方法中的局部变量在方法外不能被访问,局部内部类与局部变量同作为方法中的成员,也在方法外不能被访问。所以局部内部类在方法以外没有任何手段内被访问。
3、解决方式:只能执行局部内部类所在方法,在方法中创建局部内部类对象,对象调用类中方法,一并执行
代码示例
public class Demo09_ClassInTheMethod {
public static void main(String[] args) {
filter();
}
public static void filter() {
int num = 10;
class Kidney {
String name = "王五";
public void show() {
System.out.println(num);
}
}
Kidney k = new Kidney();
System.out.println(k.name);
k.show();
}
}
(六)匿名内部类
1、没有名字的内部类
2、使用场景:
(1)实现抽象类
(2)实现接口
3、格式:
new 抽象父类名称或接口名称() {
要实现的抽象方法
};
4、本质:
(1)匿名内部类本质上是一个实现类对象
(2)编译过后会形成一个类文件
5、内部类名称总结:
(1)有名字的内部类:
1)成员内部类:外部类名$内部类名.class
2)局部内部类:方法所在类名$1内部类名.class 其中1是书写顺序,按照升序排列:1、2、3…
(2)匿名内部类:所在类类名$1.class 其中1是书写顺序,按照升序排列:1、2、3…
代码示例
public class Demo10_NoNameClass {
public static void main(String[] args) {
/*
* ImplClass ic = new ImplClass(); ic.test();
*
* ImplInterface ii = new ImplInterface(); ii.show();
*/
// 匿名内部类本质上是个对象:是接口或者是抽象类的实现类对象
// 匿名内部类编译过后会形成一个.class文件,是一个类
TestInterface ti = new TestInterface() {
public void show() {
System.out.println("匿名内部类实现了接口!");
}
};
ti.show();
}
}
/*
* 1.抽象类
*/
abstract class TestClass {
public abstract void test();
}
class ImplClass extends TestClass {
@Override
public void test() {
System.out.println("实现子类实现了抽象类");
}
}
/*
* 2.接口
*/
interface TestInterface {
public abstract void show();
}
class ImplInterface implements TestInterface {
@Override
public void show() {
System.out.println("实现类实现了接口");
}
}
三、包
1、包:用于分类存放文件(.class)的文件夹
2、作用:
(1)分类存放文件
(2)在不同的包中,用于区分名称相同的类
3、命名:全部小写,域名倒置:
4、包的声明:使用关键字package进行声明,当前的类属于哪个包
5、效果:
(1)编译这个类,就会进入到执行的包的文件夹中
(2)编译过后,当前类的名字也发生了变化:【包名+类名】,叫做全类名
6、访问:访问其他包中的类时,需要使用全类名
7、简化:每次书写全类名非常麻烦,可以使用import关键字进行导包,在要是用的地方,引入需要使用的类。格式:import 全类名;
8、注意事项:
(1)在同一个包中,要去创建一个以上的来自于不同包的同名类对象,只能其中一个类导包,剩下的写成全类名的形式
(2)即使导入的同一个包下的类很多,也不建议使用通配符【*】
代码示例
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Random;
import java.util.Scanner;
import com.offcn.demos.Person;
public class Demo_Package {
public static void main(String[] args) {
Person p1 = new Person();
com.offcn.homework.Person p2 = new com.offcn.homework.Person();
Scanner sc = new Scanner(System.in);
int[] arr = {1};
Arrays.toString(arr);
Random r = new Random();
new ArrayList<>();
new HashSet<>();
new Date();
}
}
四、权限修饰符
1、权限修饰符,是java中的一些关键字,用于决定代码在哪里可以被访问哪里不能被访问的关键字
2、所有的权限,都是封装的体现,只是范围不同罢了
3、权限修饰符
本类 本包其他类 其他包的子类 其他包其他类
private √ X X X
默认(不写) √ √ X X
protected √ √ √(直接继承) X
public √ √ √ √