包,权限修饰符,final、枚举、抽象类、抽象方法、接口、包装类,装箱、拆箱
学习计划 包活动地址:CSDN21天学习挑战赛
什么是包?
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可以修饰类,但是该类必须是一个内部类。
在定义类时,推荐访问控制级别从严处理:
final
- 如果不允许外部直接通过 new 创建对象,构造方法必须是 private。
- 工具类不允许有 public 或 default 构造方法。
- 类非 static 成员变量并且与子类共享,必须是 protected。
- 类非static成员变量并且仅在本类使用,必须是private。
- 类 static 成员变量如果仅在本类使用,必须是 private。
- 若是 static 成员变量,必须考虑是否为 final。
- 类成员方法只供类内部调用,必须是 private。
- 类成员方法只对继承类公开,那么限制为 protected。
final的作用
- final 关键字是最终的意思,可以修饰(类、方法、变量)
- 修饰类:表明该类是最终类,不能被继承。
- 修饰方法:表明该方法是最终方法,不能被重写。
- 修饰变量:表示该变量是常量,第一次赋值后,不能再次被赋值(有且仅能被赋值一次)。
final修饰变量的注意
枚举
- final修饰的变量是基本类型:那么变量存储的数据值不能发生改变。
- final修饰的变量是引用类型:那么变量存储的地址值不能发生改变,但是地址指向的对象内容是可以发生变化的。
抽象类、抽象方法枚举是Java中的一种特殊类型,被enum修饰。
枚举的作用:是为了做信息的标志和信息的分类
格式:
格式: 修饰符 enum 枚举名称{ 第一行都是罗列枚举类实例的名称。 } 例: 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; 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。
- 枚举都是最终类,不可以被继承。
- 构造器都是私有的,枚举对外不能创建对象。
- 枚举类的第一行默认都是罗列枚举对象的名称的。
- 枚举类相当于是多例模式。
- 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错误,泛型不支持基本类型 List 正确 8大基本类型 byte short int long float double char boolean List 错误的 List 正确的
| 基本数据类型 | 包装器类型(对象类型)valueOf().parse() |
|---|---|
| boolean | Boolean |
| char | Character |
| int | Integer |
| byte | Byte |
| short | Short |
| long | Long |
| float | Float |
| double | Double |



