1.数组 数组工具类 二维数组
1.1概念
数组,标志是[ ],用于存储多个相同类型数据的集合,获取数组中的元素通过脚标(下标)来获取,数组下标是从0开始的
1.2创建数组
创建数组的方式分为两种
- 动态初始化
int[] a = new int[5] //初始化一个长度为5的数组
- 静态初始化
int b = new int[]{1,2,3,4,5}
//或者
int c = {1,2,3,4,5}
1.3 创建数组的底层实现原理
- 在内存中开辟连续的空间,用来存放数据,长度是5
- 给数组完成初始化过程,给每个元素赋予默认值,int类型默认是0
- 数组完成初始化会分配一个唯一的地址值
- 把唯一的地址值交给引用类型的变量a去保存
数组名是一个引用类型的变量,保存的是数组的地址,不是数组中的数据
数组一旦创建,长度不可变,长度允许为0
1.4练习
1.向数组中存入数据hello
package com.common.test.base;
public class TestCreateArray {
public static void main(String[] args) {
// 创建数组
// 创建静态数组
char[] a1 = new char[]{'h', 'e', 'l', 'l', 'o'};
char[] a2 = {'h', 'e', 'l', 'l', 'o'};
//创建动态数组
char[] a3 = new char[5];
a3[0] = 'h';
a3[1] = 'e';
a3[2] = 'l';
a3[3] = 'l';
a3[4] = 'o';
System.out.println(a1);
System.out.println(a2);
System.out.println(a3);
}
}
- char类型的数组底层中做了处理,可以直接打印具体元素
- 除了char类型以外的数组想要查看数组中的具体元素,需要使用数组的工具类Arrays
- arrays.toString(数组名)
package com.common.test.base;
public class TestCreateArray {
public static void main(String[] args) {
/**
* char类型的数组底层中做了处理,可以直接打印具体元素
* 除了char类型以外的数组想要查看数组中的具体元素,需要使用数组的工具类Arrays
* arrays.toString(数组名)
*/
String[] s1 = new String[3];
s1[0] = "第一";
s1[1] = "第二";
s1[2] = "第三";
String[] s2 = new String[]{"a", "b", "c"};
String[] s3 = {"a", "b", "c"};
System.out.println(s1); //打印出的是地址值[Ljava.lang.String;@6996db8
System.out.println(Arrays.toString(s1)); //[第一, 第二, 第三]
}
2.输出每个月的天数
package com.common.test.base;
public class TestArrayExec {
public static void main(String[] args) {
int[] day = {31,28,31,30,31,30,30,31,30,31,30,31};
for (int i = 0; i < day.length; i++) {
System.out.println(i+1+"月有"+day[i]+"天");
}
}
}
3.遍历数组存入1-10
package com.common.test.base;
import java.util.Arrays;
public class TestArrayExec {
public static void main(String[] args) {
m2();
}
public static void m2() {
int[] a = new int[10];
for (int i = 0; i < a.length; i++) {
a[i] = i + 1;
}
System.out.println(Arrays.toString(a));//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}
}
3.创建随机数组
package com.common.test.base;
import java.util.Arrays;
public class TestArrayExec {
public static void main(String[] args) {
m3();
}
public static void m3(){
int[] a = new int[10];
for (int i = 0; i < a.length; i++) {
a[i] = new Random().nextInt(100);
}
System.out.println(Arrays.toString(a));//[67, 90, 99, 89, 24, 52, 73, 39, 99, 24]
}
}
1.5数组工具类 Arrays
1. Arrays.toString(数组)
把数组里的数据用逗号连接成一个字符串[值1,值2]
2. Arrays.sort(数组)
对数组从小到大排序,对与基本类型的数组使用的是优化会后的快速排序算法,效率高
对于引用类型数组,使用的是优化后的合并排序算法
3.Arrays.copyOf(数组,新的长度)
把数组赋值成一个指定长度的新数组
新数组的长度 大于 原数组,相当于复制,并增加位置
新数组的长度 小于 原数组,相当于截取一部分数据
练习
1.练习Arrays.sort(数组)
package com.common.test.base;
import java.util.Arrays;
public class TestArraySort {
public static void main(String[] args) {
int[] a = {21,96,75,23,25};
Arrays.sort(a);//直接排序
System.out.println(Arrays.toString(a));//[21, 23, 25, 75, 96]
}
}
2.练习Arrays. copyOf(数组,新的长度)
package com.common.test.base;
import java.util.Arrays;
public class TestArraysCopyOf {
public static void main(String[] args) {
//1.创建数组
int[] from = {1,2,3,4,5};//数组一旦创建,长度不可改变
//2.1 数组的普通复制
/**copyOf()用于完成数组的复制,两个参数:
* 参数1:要复制哪个数组
* 参数2:新数组的长度*/
int[] to = Arrays.copyOf(from, 5);
System.out.println(Arrays.toString(to));
//2.2数组的扩容
/**扩容:给数组扩大容量,新数组的长度>原数组的长度
* 扩容思路:先创建对应长度的新数组,每个位置上都是默认值0
* 然后从原数组中将元素复制到新数组,没有被覆盖的元素还是默认值0*/
int[] to2 = Arrays.copyOf(from, 10);
System.out.println(Arrays.toString(to2));
//2.3数组的缩容
/**缩容:缩小数组的容量,新数组的长度<原数组的长度
* 缩容思路:先创建对应长度的新数组,每个位置上都是默认值0
* 然后从原数组中复制指定个数的元素到新数组中,类似于截取*/
int[] to3 = Arrays.copyOf(from, 3);
System.out.println(Arrays.toString(to3));
//2.4指定首尾截取原数组中的元素
/**copyOfRange()用于完成数组的截取,3个参数:
* 参数1:要截取哪个数组【原数组】
* 参数2:从原数组的哪个下标开始
* 参数3:到原数组的哪个下标结束
* 注意:截取的元素包含开始下标处的元素,不包含结束下标处的元素*/
int[] to4 = Arrays.copyOfRange(from, 2, 4);
System.out.println(Arrays.toString(to4));
}
}
1.5二维数组
创建二维数组
int[][] a1 = new int[3][3];
int[][] a2 = {{3,5},{7,9},{1,2}};
练习
package com.common.test.base;
public class TestArray2 {
public static void main(String[] args) {
String[][] a = new String[5][5];
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
a[i][j] = " * ";
}
}
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
//a[i][j]--根据外部数组的下标和内部数组的下标定位具体的元素
System.out.print(a[i][j]);
}
System.out.println();
}
}
}
2.冒泡排序
package com.common.test.base;
import java.util.Arrays;
public class TestBubbleSort {
public static void main(String[] args) {
//1.创建一个无序的数组
int[] a = {27, 96, 73, 25, 21};
//2.调用method()完成排序
int[] newA = method(a);
System.out.println("排序完毕:" + Arrays.toString(newA));
}
public static int[] method(int[] a) {
//1.外层循环,控制比较的轮数,假设有n个数,最多比较n-1次
//开始值:1 结束值:<= a.length-1 变化:++
//控制的是循环执行的次数,比如5个数,最多比较4轮,<= a.length-1,最多取到4,也就是[1,4]4次
for (int i = 1; i <= a.length - 1; i++) {
System.out.println("第" + i + "轮:");
//2.内层循环:相邻比较+互换位置
for (int j = 0; j < a.length - i; j++) {
//相邻比较,a[j]代表的就是前一个元素,a[j+1]代表的就是后一个元素
if (a[j] > a[j + 1]) {
//交换数据
int t = a[j];
a[j] = a[j + 1];
a[j + 1] = t;
//System.out.println("第"+(j+1)+"次比较交换后:"+Arrays.toString(a));
}
}
System.out.println("第" + i + "轮的结果:" + Arrays.toString(a));
}
return a;//把排序好的数组a返回
}
}
优化后
public static int[] bubbleSort(int[] a){
for (int i = 1; i < a.length-1; i++) {
boolean flag = false;
System.out.println("第"+i+"轮:");
for (int j = 0; j < a.length-i; j++) {
if (a[j]>a[j+1]){
int t = a[j];
a[j] = a[j+1];
a[j+1] = t;
flag = true;
}
}
System.out.println("第" + i + "轮的结果:" + Arrays.toString(a));
if (flag == false) {
return a;
}
}
return a;//把排序好的数组a返回
}
3.面向对象 类 对象 封账
3.1面向对象的概念
3.2面向对象的三大特征
封装
封装是隐藏对象的属性和实现细节,仅对外提供公共的访问方式
优点:
1.提高安全性
2.提高重用性
使用private关键字来封装成员变量与方法
setXxx – 对外提供公共的设置值方式
getXxx – 对外提供公共的获取值方式
关于成员方法:
把私有方法放在公共方法里供外界调用即可
练习封装的必要性
package com.common.test.base;
public class TestPrivate {
public static void main(String[] args) {
User user = new User();
user.name = "陈小吨";
user.setIdCard(123456);
Integer idCard = user.getIdCard();
System.out.println(idCard);
System.out.println(user.name);
}
}
class User{
String name;
private Integer idCard;
public Integer getIdCard(){
return idCard;
}
public void setIdCard(Integer idCard){
this.idCard = idCard;
}
}
继承
继承是从已有的类中派生出新的类,新类能吸收已有类的数据属性和行为,并扩展最新的功能
- 通过extend子类继承父类 构成子类与父类的继承关系
- 子类继承父类相当于子类复制了一份父类的功能
- 子类无法继承父类的私有方法,无法继承构造方法
- 支持单继承,具有传递性,耦合性非常强
- 子类可以修改父类的功能,也可扩展自己的功能
继承的方法 :继承方法重写规则(两同两小一大)
两同:方法名相同,参数列表相同
两小:子类的返回值类型要小于父类的返回值类型,子类 抛出的异常类型 要小于父类的抛出的异常类型
一大:子类的修饰符要大于或等于父类的权限修饰符
子类创建对象时默认会先调用父类的构造方法
重写与重载
1.重载是指一个类中有多个同名方法,但参数列表不同;重写的前提是继承,子类修改父类的功能便是重写
2.重载的意义是方便外界的调用;重写的意义是在不修源码的情况下对功能进行扩展
super
可以把super 看做是父类的对象
- 当父类的成员变量与子类的变量同名时,使用super指定父类的成员变量
- 使用super在子类构造方法的第一行调用父类构造方法的功能
super()调用的是父类的无参构造
super(参数)调用的是父类对应的含参构造
在构造方法里,super出现的调用位置必须是第一行
- 1.子类在创建对象时,默认会先调用父类的构造方法
- 2.原因是子类构造函数中的第一行默认存在super();–表示调用父类的无参构造
- 3.当父类没有无参构造时,可以通过super(参数)调用父类的其他含参构造
- 子类必须调用一个父类的构造函数,不管是无参还是含参,选一个即可
- 4.构造方法不可以被继承!因为语法的原因:要求构造方法的名字必须是本类类名
- 不能在子类中出现一个父类名字的构造方法
this 与super的区别
案例
- 继承入门案例
package com.common.test.base;
public class TestExtend {
public static void main(String[] args) {
Animal animal = new Animal();
Cat cat = new Cat();
Miao miao = new Miao();
animal.eat();
cat.eat();
miao.eat();
}
}
class Animal {
public void eat() {
System.out.println("动物吃东西!");
}
}
class Cat extends Animal {
int a = 10;
private int b = 100;//私有属性
}
class Miao extends Cat {
public void study(){
System.out.println("正在学习");
System.out.println(a);
}
}
- super之继承中成员变量使用
package com.common.test.base;
public class ExtendDemo {
public static void main(String[] args) {
Son son = new Son();
son.study();
}
}
class Father {
int sum = 1;
int count = 2;
}
class Son extends Father {
int sum = 10;
public void study() {
System.out.println("好好学习");
int sum= 100;//局部变量
System.out.println(sum);
System.out.println(this.sum);//成员变量
System.out.println("打印父类的成员变量"+ super.sum);
System.out.println(count);
}
}
- super之继承中构造方法的使用
package com.common.test.base;
/*本类用于测试继承中构造方法的使用
* 1.子类在创建对象时,默认会先调用父类的构造方法
* 2.原因是子类构造函数中的第一行默认存在super();--表示调用父类的无参构造
* 3.当父类没有无参构造时,可以通过super(参数)调用父类的其他含参构造
* 子类必须调用一个父类的构造函数,不管是无参还是含参,选一个即可
* 4.构造方法不可以被继承!因为语法的原因:要求构造方法的名字必须是本类类名
* 不能在子类中出现一个父类名字的构造方法
* */
public class ExtendDemo2 {
public static void main(String[] args) {
Son2 son2 = new Son2();
}
}
class Father2{
public Father2(String name){
System.out.println("父类的含参构造" +name);
}
}
class Son2 extends Father2{
public Son2(){
super("子类调用");
System.out.println("子类的无参构造");
}
}
- 练习:继承中成员方法的使用
package com.common.test.base;
public class ExtendDemo3 {
public static void main(String[] args) {
Father3 father3 = new Father3();
Son3 son3 = new Son3();
son3.eat();
father3.eat();
}
}
class Father3{
public void eat(){
System.out.println("爸爸爱吃蔬菜");
}
}
class Son3 extends Father3{
@Override
public void eat() {
System.out.println("儿子爱吃肉");
}
}
多态
多态是一个重要特征,指
- 多态的前提是继承+重写 同一个实体具有多种形态
- 声明看父类,实现看子类
- 多态对象使用的成员变量是父类的
- 若使用的方法重写了则使用的就是子类的
- 静态资源谁调用就是谁的
- 父类引用指向子类对象
3.3类和对象
类
- java语言最基本的单位
- 一类事务抽取共同属性与功能形成的
对象
每个对象有三个特点:对象的属性,对象的功能和对象的标识
- 对象的属性用来描述对象的基本特征
- 对象的功能用来描述对象可以完成的操作
- 对象的标识是指每个对象在内存中都有一个唯一的地址值用于与其他对象进行区分,类似于身份证号
类和对象的关系
- 先创建类,再通过类创建对象
- 通过一个类创建多个对象
- 类时抽象的,对象是具体的
对象在内存中的存储 **
对象的创建过程分析:
Person person = new Person();
- 在栈内存中开辟一片空间,存放引用类型Person类型的变量 person
- 在堆内存中开辟一块空间,存放Person 类型的对象
- 给对象进行初始化
- 当对象准备好后,生成一个唯一的地址值,然后将地址值交给引用类型的变量person来保存
访问修饰符
4.static final 静态/构造/局部代码块之间的关系
4.1 static
4.1.1 概念
java中的关键字,用于修饰成员变量和成员方法
4.1.2 特点
1.static可以修饰成员变量和方法
2.被static修饰的资源称为静态资源
3.静态资源随着类的加载而加载,最先加载,优先于对象进行加载
4.静态资源可以通过类名直接调用,也被称作类资源
5.静态被全局所有对象共享,值只有一份
6.静态资源只能调用静态资源
7.静态区域内不允许使用this与super关键字
4.1.3 练习
- static入门案例
package com.common.test.base;
public class TestStatic1 {
public static void main(String[] args) {
Fruit.kind= "苹果"; //静态成员变量可以通过类名.属性名 调用
Fruit.clean(); //静态成员方法可以直接类名.方法 调用
Fruit fruit = new Fruit();
fruit.weight = 20D;
fruit.grow();
}
}
class Fruit {
static String kind;
double weight;
public static void clean() {
System.out.println("洗水果");
}
public void grow(){
System.out.println("种一颗果树");
}
}
- static静态调用关系
package com.common.test.base;
public class TestStatic2 {
}
class Teacher {
//定义普通属性与普通方法
String name;
public void teach() {
System.out.println("正在教课");
//非静态资源可以调用静态资源
System.out.println(age);
ready();
}
static int age;
public static void ready() {
System.out.println("正在备课");
//静态资源不可以调用普通资源
// System.out.println(name);
// teach();
}
public static void eat() {
System.out.println("正在吃饭中");
//静态资源可以调用静态资源
System.out.println(age);
ready();
}
}
4.2静态代码块、构造代码块、局部代码块
4.2.1 静态代码块格式
static{}
静态资源随着类的加载而加载,并且只被加载一次,一般用于项目的初始化
特点: 被static修饰,位置在类里方法外
4.2.2 三种代码块的比较
- 静态代码块:在类加载时就加载,并且只被加载一次,一般用于项目的初始化
- 构造代码块:在创建对象时会自动调用,每次创建对象都会被调用,提取构造共性
- 局部代码块:方法里的代码块,限制局部变量的范围
**执行顺序:**静态代码块 --> 构造代码块 --> 构造方法 --> 局部代码块
4.2.3 练习
- 几种代码块的关系
package com.common.test.base;
public class TestStaticBlock {
public static void main(String[] args) {
Person person = new Person();
person.play();
}
}
class Person {
/**
* 静态代码块
* 类里方法外
* 随着类的加载而加载,优先于对象加载,并且只会加载一次
*/
static {
System.out.println("我是静态代码块");
}
/**
* 构造代码块
* 类里方法外
* 每次创建对象时触发,优先于构造方法执行
*/
{
System.out.println("我是构造代码块");
}
/**
* 构造方法
*
*/
public Person(){
System.out.println("我是构造方法");
}
/**
* 普通方法
*/
public void play(){
{
System.out.println("我是局部代码块");
}
System.out.println("我是普通方法");
}}
4.3 final
4.3.1 概念
final 关键字可以修饰类,方法,字段(属性)
java出现继承后,子类可以继承父类的功能,当父类功能不允许子类改变时,可以利用final关键字修饰父类
4.3.2 特点
1.被final修饰的变量是常量,必须赋值且不能被修改
2.被final修饰的方法不能被重写
3.被final修饰的类不能被继承
5.异常
5.1 概述
异常是一些用来封装错误信息的对象
由异常的类型、提示信息、报错的行号提示三部分组成
5.2异常的继承结构
Throwable:顶级父类
Error:错误,程序无法处理
内存移除
Exception:编码可以修复的错误
运行时异常
IO异常
编译错误(checked异常);
运行时错误(unchecked异常);
逻辑错误;
编译错误是因为程序没有遵循语法规则,编译程序能够自己发现并且提示我们错误的原因和位置,这个也是大家在刚接触编程语言最常遇到的问题。
运行时错误是因为程序在执行时,运行环境发现了不能执行的操作。
逻辑错误是因为程序没有按照预期的逻辑顺序执行。异常也就是指程序运行时发生错误,而异常处理就是对这些错误进行处理和控制。
5.3异常的处理方式
通常有两种处理方式:捕获或者向上抛出
5.4throws 与 throw 的区别
throws
用在方法声明处,其后跟着的是异常类的名字
表示此方法会抛出异常,需要由本方法的调用者来处理这些异常
但是注意:这只是一种可能性,异常不一定会发生
throw
用在方法的内部,其后跟着的是异常对象的名字
表示此处抛出异常,由方法体内的语句处理
注意:执行throw一定抛出了某种异常
5.4 练习
package com.common.test.base;
import java.util.InputMismatchException;
import java.util.Scanner;
/*本类用于异常的入门案例*/
public class ExceptionDemo {
//public static void main(String[] args) throws Exception {//问题实际未处理,还报错
public static void main(String[] args) {
//method1();//调用暴露异常的方法
//method2();//调用解决异常的方法--异常解决方案1--捕获处理--自己解决
/*main()不直接调用会抛出异常的method3()
* 而是调用f(),f()解决了method3()可能会抛出的异常*/
f();
//method3();//调用解决异常的方法--异常解决方案2--向上抛出--交给调用者来解决
}
//相当于在main()调用method3()之前解决了method3()可能会抛出的异常
private static void f() {
try {
method3();
}catch (Exception e){
System.out.println("您输入的数据不对~请重新输入!");
}
}
/*如果一个方法抛出了异常,那么谁来调用这个方法,谁就需要处理这个异常
* 这里的处理也有两种方案:捕获解决 或者 继续向上抛出
* 但注意:我们一般会在main()调用之前将异常解决掉
* 而不是将问题抛给main(),因为没人解决了,该报错还报错*/
/*异常抛出的格式:在方法的小括号与大括号之间,写:throws 异常类型
* 如果有多个异常,使用逗号分隔即可*/
//0.定义一个解决异常的方法-方案2
//private static void method3() throws ArithmeticException,InputMismatchException{
private static void method3() throws Exception{
//1.复写一下刚刚的代码
System.out.println("请您输入要计算的第一个整数:");
int a = new Scanner(System.in).nextInt();
System.out.println("请您输入要计算的第二个整数:");
int b = new Scanner(System.in).nextInt();
System.out.println(a/b);
}
/*异常捕获处理的格式:
* try{
* 可能会抛出异常的代码
* }catch(异常的类型 异常的名字){
* 万一捕获到了异常,进行处理的解决方案
* }
* try-catch结构可以嵌套,如果有多种异常类型需要特殊处理的话
* */
//0.定义一个解决异常的方法-方案1
private static void method2() {
//1.按照捕获处理的格式完成结构
try{
//2.复写一下刚刚的代码
System.out.println("请您输入要计算的第一个整数:");
int a = new Scanner(System.in).nextInt();
System.out.println("请您输入要计算的第二个整数:");
int b = new Scanner(System.in).nextInt();
System.out.println(a/b);
}catch(ArithmeticException e){//异常类型 异常名
System.out.println("除数不能为0!");
}catch (InputMismatchException e){
System.out.println("请输入规定的整数类型!");
/*使用多态的思想,不论是什么子异常,统一看作父类型Exception
* 做出更加通用的解决方案,甚至可以只写这一个,上面2个不写了*/
}catch (Exception e){
System.out.println("您输入的数据不对~请重新输入!");
}
}
//0.定义一个用来暴露异常的方法
private static void method1() {
//1.提示并接收用户输入的两个整数
System.out.println("请您输入要计算的第一个整数:");
int a = new Scanner(System.in).nextInt();
System.out.println("请您输入要计算的第二个整数:");
int b = new Scanner(System.in).nextInt();
//2.输出两个数除法的结果
//输入11和0,报错:ArithmeticException--算术异常,除数不能为0,数学规定
//输入11和3.4,报错:InputMismatchException--输入不匹配异常
System.out.println(a/b);
/*1.不要害怕BUG,真正的勇士敢于直面自己写的BUG*/
/*2.学会看报错的信息提示,确定自己错误的方法*/
/*3.学会看报错的行号提示,确定自己报错的位置,哪里不对点哪里
* 注意:源码不会错,要看的是自己写的代码*/
}
}
6.抽象
6.1 概念
Java中可以定义被abstract关键字修饰的方法,这种方法只有声明,没有方法体,叫做抽象方法.
Java中可以定义被abstract关键字修饰的类,被abstract关键字修饰的类叫做抽象类
如果一个类含有抽象方法,那么它一定是抽象类
抽象类中的方法实现交给子类来完成
6.2 抽象方法的格式
6.3 特点
- abstract 可以修饰方法或者类
- 被abstarct修饰的类叫做抽象类,被abstract修饰的方法叫做抽象方法
- 抽象类中可以没有抽象方法;
- 如果类中有抽象方法,那么该类必须定义为一个抽象类
- 子类继承了抽象类以后,要么还是一个抽象类,要么就把父类的所有抽象方法都重写
- 多用于多态中
- 抽象类不可以被实例化
6.4abstract注意事项
抽象方法要求子类继承后必须重写。
那么,abstract关键字不可以和哪些关键字一起使用呢?以下关键字,在抽象类中。用是可以用的,只是没有意义了。
1.private:被私有化后,子类无法重写,与abstract相违背。
2.static:静态优先于对象存在,存在加载顺序问题。
3.final:被final修饰后,无法重写,与abstract相违背。
6.5案例
package com.common.test.base;
public class AbstractDemo3 {
}
abstract class Fruit1{
/*抽象类中可以定义成员变量*/
int sum = 100;
/*抽象类中可以定义成员常量*/
final String name = "葡萄";
/*抽象类中可以定义普通方法,也可以都是普通方法*/
public void clean(){
System.out.println("洗水果");
}
/* 抽象类中可以定义抽象方法,这个类必须是抽象类*/
//抽象类中可以没有抽象方法,但是抽象方法必须在抽象类中
public abstract void grow();
public abstract void clean2();
}
//2.创建子类Banana
/*如果一个子类继承了抽象父类,有两种处理方案:
* 方案一:继续抽象,也就是作为抽象子类,无需实现抽象方法-"躺平"
* 方案二:不再抽象,实现继承自父类中的所有未实现的抽象方法-"父债子偿"*/
abstract class Apple extends Fruit1{
}
class Banana extends Fruit1{
@Override
public void grow() {
}
@Override
public void clean2() {
}
}
7.接口
7.1概念
7.2格式
interface 接口名 {代码}
7.3 特点
- 通过interface关键字来定义接口
- 通过implements让子类来实现接口
- 接口中的方法全部都是抽象方法(JAVA8)
- 可以把接口理解成一个特殊的抽象类(但接口不是类!!!)
- 类描述的是一类事物的属性和方法,接口则是包含实现类要实现的方法
- 接口突破了java单继承的局限性
- 接口和类之间可以多实现,接口与接口之间可以多继承
- 接口是对外暴露的规则,是一套开发规范
- 接口提高了程序的功能拓展,降低了耦合性