✨✨个人主页:沫洺的主页
📚📚系列专栏: 📖 JavaWeb专栏📖 JavaSE专栏 📖 Java基础专栏📖vue3专栏
📖MyBatis专栏📖Spring专栏📖SpringMVC专栏📖SpringBoot专栏
📖Docker专栏📖Reids专栏📖MQ专栏📖SpringCloud专栏
💖💖如果文章对你有所帮助请留下三连✨✨
🍃包
什么是包?
package就是包
包的作用
- 包是用来分门别类的管理各种不同类的,类似于文件夹、建包利于程序的管理和维护。
- 组织相关的源代码文件
- 不同包中的类名可以相同,用来避免名字冲突
- 提供包一级的封装和存取权限
建包的语法格式
公司里包的格式一般是:package 公司域名倒写.技术名称。报名建议全部英文小写,且具备意义
建包的注意事项
- 定义包的语句必须在第一行,一般IDEA工具会帮助创建
- 包定义语句不是必须的,如果没有定义包,则当前编译单元属于无名包,生成的class文 件一般放在与.java文件同目录。
🌺导包
- Java 是单继承,多实现,每个java类,都会默认继承Object类,java.lang包下的所有类和同包下的类,在程序运行时,不用导入直接使用,java.lang.String java.lang.System类都是不用导入,直接使用的.
- Java编译器会自动引入包java.lang,同包下的内容,对于其他的包,如果程序中使用到包中的类,则必须使用import引入。
- 相同包下的类可以直接访问、相互引用,也不需要导入。不同包下的类必须导包,才可以使用!导包格式:import 包名.类名;
- 假如一个类中需要用到不同类,而这个两个类的名称是一样的,那么默认只能导入一个类,另一个类要带包名访问。
IDEA工具开启自动导包
🌲权限修饰符
💐作用域(public、private、protected、default)
作用域 | 当前类 | 同一个package下(朋友) | 子孙类 | 其他package |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
default | √ | √ | × | × |
private | √ | × | × | × |
public : 公共权限
public表明该数据成员、成员函数是对所有用户开放的,所有用户都可以直接进行调用
修饰对象:类、方法、属性
继承: 被public所修饰的成员能被该类的所有子类继承下来。
作用域: 可以被任意类访问
- public能用来修饰类,在一个java源文件中只能有一个类被声明为public,而且一旦有一个类为public,那这个java源文件的文件名就必须要和这个被public所修饰的类的类名相同,否则编译不能通过。
- 一个类作为外部类的时候只能被public或者默认访问修饰符所修饰,但是一个类如果作为内部类的时候,则可以被四种访问修饰符所修饰,因为一个类作为内部类的时候,就作为外部类的一个成员属性了,因此可以有四种访问修饰符修饰,这是内部类和外部类的一个区别。
- public用来修饰类中成员(变量和方法),被public所修饰的成员可以在任何类中都能被访问到。通过操作该类的对象能随意访问public成员。
protected:受保护的权限
protected对于子女、朋友来说,就是public的,可以自由使用,没有任何限制,而对于其他的外部class,protected就变成private。也就是其他package的成员不能使用。
修饰对象:修饰内部类,接口,属性,方法
继承: 被protected所修饰的成员能被该类的所有子类继承下来。
作用域: 可以被同包类访问,如果不是同包,必须是该类的子类才能访问
- protected不能修饰类。
- protected的作用域为可以被同胞类访问,如果不是同胞 ,则必须在该类的子类范围内且必须是子类对象才能访问
default : 同包权限(默认,缺省的)
不写时默认default,统一包下的成员可以使用
修饰对象:修饰类,属性,方法。
继承:被default所修饰的成员只能被该类所在同一个package中的子类所继承下来。(也就是说只有在同一个package中的子类才能访问到父类中default修饰的成员)
作用域: 只能被同包的类访问
private : 私有权限
private表示私有,私有的意思就是除了class自己直接用之外,任何人都不可以直接使用(但是可以间接使用)。
修饰对象 : 内部类,属性,方法
作用域: 只能在本类中使用
- priavte可以修饰类,但是该类必须是一个内部类。
在定义类时,推荐访问控制级别从严处理:
- 如果不允许外部直接通过 new 创建对象,构造方法必须是 private。
- 工具类不允许有 public 或 default 构造方法。
- 类非 static 成员变量并且与子类共享,必须是 protected。
- 类非static成员变量并且仅在本类使用,必须是private。
- 类 static 成员变量如果仅在本类使用,必须是 private。
- 若是 static 成员变量,必须考虑是否为 final。
- 类成员方法只供类内部调用,必须是 private。
- 类成员方法只对继承类公开,那么限制为 protected。
🌹final
final的作用
- final 关键字是最终的意思,可以修饰(类、方法、变量)
- 修饰类:表明该类是最终类,不能被继承。
- 修饰方法:表明该方法是最终方法,不能被重写。
- 修饰变量:表示该变量是常量,第一次赋值后,不能再次被赋值(有且仅能被赋值一次)。
final修饰变量的注意
- final修饰的变量是基本类型:那么变量存储的数据值不能发生改变。
- final修饰的变量是引用类型:那么变量存储的地址值不能发生改变,但是地址指向的对象内容是可以发生变化的。
🌷枚举
为了间接的表示一些固定的值,Java就给我们提供了枚举
是指将变量的值一一列出来,变量的值只限于列举出来的值的范围内
枚举是Java中的一种特殊类型,被enum修饰。
枚举的作用:是为了做信息的标志和信息的分类
格式:
注意: 定义枚举类要用关键字enum 格式: 修饰符 enum 枚举名称{ 枚举项1,枚举项2,枚举项3; 第一行都是罗列枚举类实例的名称。 } 例: enum Season{ SPRING , SUMMER , AUTUMN , WINTER; }
举个案例:
枚举类(MessageEnum)
package enum2; public enum MessageEnum { SAVE(100,"保存"), OPEN(800,"打开"), ERROR(400,"错误"), MESSAGE(200,"成功"), INFO(202,"信息提示"), DEBUG(404,"调试"); private int code; private String msg; public int getCode() { return code; } public String getMsg() { return msg; } private MessageEnum(int code, String msg){ this.code=code; this.msg=msg; } public static MessageEnum fromTypeCode(int code){ if(code>=1000){ return ERROR; } for (MessageEnum type : MessageEnum.values()) { if(type.code==code){ return type; } } return null; } static MessageEnum fromTypeMsg(String msg){ for (MessageEnum type : MessageEnum.values()) { if(type.msg==msg){ return type; } } return null; } }
测试类(MessageEnumDemo)
package enum2; /** * SAVE(100,"保存"), * OPEN(800,"打开"), * ERROR(400,"错误"), * MESSAGE(200,"成功"), * INFO(202,"信息提示"), * DEBUG(404,"调试"); */ public class MessageEnumDemo { public static void main(String[] args) { var e = MessageEnum.MESSAGE; //e=MessageEnum.fromTypeCode(1000); e=MessageEnum.fromTypeMsg("调试"); switch(e){ case SAVE -> { System.out.println(e.getCode()+"=="+e.getMsg()); } case OPEN -> { System.out.println(e.getCode()+"=="+e.getMsg()); } case MESSAGE -> { System.out.println(e.getCode()+"=="+e.getMsg()); } case ERROR -> { System.out.println(e.getCode()+"=="+e.getMsg()); } case INFO -> { System.out.println(e.getCode()+"=="+e.getMsg()); } case DEBUG -> { System.out.println(e.getCode()+"=="+e.getMsg()); } default -> { System.out.println("未知操作"); } } } }
404==调试
枚举的特征
- 枚举类都是继承了枚举类型:java.lang.Enum,所有枚举类都是Enum的子类
- 枚举都是最终类,不可以被继承。
- 构造器都是私有的,枚举对外不能创建对象。
- 枚举类的第一行默认都是罗列枚举对象的名称的。
- 枚举类相当于是多例模式。
我们可以通过"枚举类名.枚举项名称"去访问指定的枚举项
每一个枚举项其实就是该枚举的一个对象
枚举也是一个类,也可以去定义成员变量
枚举类的第一行上必须是枚举项,最后一个枚举项后的分号是可以省略的,但是如果枚举类有其他的东西,这个分号就不能省略。建议不要省略
枚举类可以有构造器,但必须是private的,它默认的也是private的。
枚举项的用法比较特殊:枚举("");
枚举类也可以有抽象方法,但是枚举项必须重写该方法
package cn.moming3; public enum Season { SPRING("春"){ //如果枚举类中有抽象方法 //那么在枚举项中必须要全部重写 @Override public void show() { System.out.println(this.name); } }, SUMMER("夏"){ @Override public void show() { System.out.println(this.name); } }, AUTUMN("秋"){ @Override public void show() { System.out.println(this.name); } }, WINTER("冬"){ @Override public void show() { System.out.println(this.name); } }; public String name; //空参构造 //private Season(){} //有参构造 private Season(String name){ this.name = name; } //抽象方法 public abstract void show(); }
枚举的方法
方法名 说明 String name() 获取枚举项的名称 int ordinal() 返回枚举项在枚举类中的索引值 int compareTo(E o) 比较两个枚举项,返回的是索引值的差值 String toString() 返回枚举常量的名称 static <T> T valueOf(Class<T> type,String name) 获取指定枚举类中的指定名称的枚举值 values() 获得所有的枚举项
代码示例
package cn.moming3; import java.util.Arrays; public class EnumDemo { public static void main(String[] args) { //获取枚举项的名称 String name = Season.SPRING.name; System.out.println(name); //返回枚举项在枚举中的索引值 int index = Season.SPRING.ordinal(); System.out.println(index); //比较两个枚举项,返回的是索引值的差值 int result = Season.SPRING.compareTo(Season.WINTER); System.out.println(result); //返回枚举常量的名称 String s = Season.SPRING.toString(); System.out.println(s); //获取指定枚举类中的指定名称的枚举值 Season spring = Enum.valueOf(Season.class, "SPRING"); System.out.println(spring); System.out.println(Season.SPRING==spring); //获取所有的枚举项 Season[] values = Season.values(); System.out.println(Arrays.toString(values)); } }
春 0 -3 SPRING SPRING true [SPRING, SUMMER, AUTUMN, WINTER]
🌻抽象类、抽象方法
- abstract修饰类,这个类就是抽象类;修饰方法,这个方法就是抽象方法。
java语言中,抽象方法是说没有方法的实现(方法体)此方法为抽象方法,只有抽象类和接口中才可以有抽象方法。- 抽象方法只有方法签名,不能写方法体。
- 一个类中定义了抽象方法,这个类必须声明成抽象类。
- 一个类如果继承了抽象类,那么这个类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。
格式: 修饰符 abstract class 类名{ 修饰符 abstract 返回值类型 方法名称(形参列表); } 例: public abstract class Animal{ public abstract void run(); }
抽象的使用场景
- 抽象类可以理解成不完整的设计图,一般作为父类,让子类来继承。
- 当父类知道子类一定要完成某些行为,但是每个子类该行为的实现又不同,于是该父类就把该行为定义成抽象方法的形式,具体实现交给子类去完成。此时这个类就可以声明成抽象类。
特征和注意事项
- 类有的成员(成员变量、方法、构造器)抽象类都具备
- 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
- 一个类继承了抽象类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。
- 不能用abstract修饰变量、代码块、构造器。
- 最重要的特征:得到了抽象方法,失去了创建对象的能力(有得有失)
final和abstract的关系
- 互斥关系 abstract定义的抽象类作为模板让子类继承,final定义的类不能被继承。
- 抽象方法定义通用功能让子类重写,final定义的方法子类不能重写。
🌾接口
接口interface,使用interface修饰
- 接口是静态常量和抽象方法的集合
- 静态常量默认被 public static final修饰
- 抽象方法, 默认被public abstract修饰
- java 8.0 接口增加了静态实现方法和默认实现方法
//普通类 public class 类名{ //成员变量 - 属性 //成员方法 - 行为 //构造方法 } //接口 public interface 接口名{ //静态常量 //抽象方法 }
接口的特点
- 接口不能实例化 (因为里面可能有抽象方法,所以不能直接使用)
- 如果实现类不是抽象类的话,必须重写所有接口中的抽象方法
实现接口
- 定义一个类去实现接口 implements
- 重写所有抽象方法
- 创建实现类的对象 , 使用这个对象调用方法
接口(A)
package cn.moming6; public interface A{ //public static final int AGE = 18; int AGE = 18; //静态常量,可以省略public static final //public abstract int getLf(int i); int getLf(int i); //抽象方法没有方法体,可以省略public abstract //public default void hello(String name){} default void hello(String name){//默认实现方法,可以省略public System.out.println("你好"+name); } //public static void welcome(String name){} static void welcome(String name){//静态实现方法,可以省略public System.out.println("欢迎"+name); } }
实现类(B)
package cn.moming6; public class B implements A { @Override public int getLf(int i) { //实现类必须重写接口抽象方法 return i*i*i; } public int getPf(int i){ //实现类自己的方法 return i*i; } }
测试类(Test)
package cn.moming6; public class Test { public static void main(String[] args) { System.out.println(A.AGE); System.out.println(B.AGE); A.welcome("沫洺");//接口中的静态方法只能通过接口调用 System.out.println("==========="); B b = new B(); //实例化实现类 b.hello("沫洺"); //实现类实例化对象调用接口中的默认方法 System.out.println(b.getLf(3));//调用抽象方法 System.out.println(b.getPf(3));//调用自己的方法 System.out.println("==========="); A a = new B(); //多态 a.hello("沫洺"); System.out.println(a.getLf(2)); //b.getPf(3) 无法调用实现类自己的方法 } }
18 18 欢迎沫洺 =========== 你好沫洺 27 9 =========== 你好沫洺 8
注意
- 接口中没有构造方法(接口中都是静态成员变量,静态成员变量加载时是不用创建对象的)
- 接口与接口的多继承中,相同方法名的默认方法优先于抽象方法
为什么要有接口默认方法?
举一个很现实的例子:
我们的接口老早就写好了,后面因为各种业务问题,避免不了要修改接口。
在 Java 8 之前,比如要在一个接口中添加一个抽象方法,那所有的接口实现类都要去实现这个方法,不然就会编译错误,而某些实现类根本就不需要实现这个方法也被迫要写一个空实现,改动会非常大。
所以,接口默认方法就是为了解决这个问题,只要在一个接口添加了一个默认方法,所有的实现类就自动继承,不需要改动任何实现类,也不会影响业务,爽歪歪。
另外,接口默认方法可以被接口实现类重写,又因为接口之间可以多继承,所以就会出现多继承带来的冲突问题,不知道继承谁,只能通过重写解决。
为什么要有接口静态方法?
接口静态方法和默认方法类似,只是接口静态方法不可以被接口实现类重写。
接口静态方法只可以直接通过静态方法所在的 接口名.静态方法名 来调用。
- 类与类------单继承、多层继承
- 类与接口------多实现
- 接口与接口------多继承
接口为什么可以多继承呢?因为没有冲突,接口中最初设计的时候只能有抽象方法,没有方法体,所以不会冲突。//声明接口A继承C D E F相关的接口 interface A extends C,D,E,F{ } //声明类F 并继承E类,同时实现D,C,B,A 等接口 publc class F extends E implements D,C,B,A{ } //这就是我们说的java单继承多实现
抽象类和接口的区别
- 抽象类:可以有抽象方法,也可以有实现方法,如果有抽象方法,则必须为抽象类,使用它的子类,如果子类没有实现所有抽象方法,那子类也必须为抽象类。
- 接口:可以有全局常量,全局抽象方法,全局static 静态实现方法,全局default默认实现方法。
- java1.8对接口已经可以有直接实现的方法功用,还有如果一个接口只有一个抽象方法,自动为函数式接口。
- 抽象父类中的抽象方法的作用: 定义规则和规范的,子类必须重写所有抽象方法。
- 接口作用(方法默认是抽象的): 定义规则和规范,实现类必须重写所有抽象方法。
- 父类定义共性内容,接口定义特性内容。
🍃装箱、拆箱
Integer i1 = 128; // 装箱,相当于 Integer.valueOf(128);
int t = i1; //相当于 i1.intValue() 拆箱
基本类型和包装器类型的转换 List<int>错误,泛型不支持基本类型 List<Integer>正确
8大基本类型 byte short int long float double char boolean
List<int> 错误的
List<Integer> 正确的
基本数据类型 | 包装器类型(对象类型)valueOf().parse() |
---|---|
boolean | Boolean |
char | Character |
int | Integer |
byte | Byte |
short | Short |
long | Long |
float | Float |
double | Double |