详细介绍一下Java中public class和缺省class的区别

Java public class 与 缺省(无修饰符)class 完整详细区别

前置概念

  1. public:访问修饰符,公共权限;
  2. 缺省类 :类前面不写任何修饰符(既无public、private、protected),官方名称为包访问权限 / 包私有权限
  3. 以下对比只针对顶层类(直接写在.java文件中,不是方法/类内部的内部类)。

一、源文件语法强制规则(编译直接报错,硬性规定)

1. public class 规则

  1. 单个.java文件最多只能有1个 public class,不能存在多个;
  2. public修饰的类名,必须和当前.java文件名完全相同,大小写严格区分
    示例:文件 Person.java
java 复制代码
// 合法
public class Person {}

// 普通缺省类,允许存在多个
class Test1 {}
class Test2 {}

错误案例:文件 Person.javapublic class User{} → 编译失败。

2. 缺省class规则

  1. 一个java文件可以写任意多个缺省class,数量无限制;
  2. 类名与java文件名无任何绑定,叫什么都可以;
    示例:Demo.java
java 复制代码
class A{}
class B{}
class C{}

完全合法,无编译报错。

二、访问权限(核心本质区别)

1. public class

权限:全局可见,任意包都能访问

  • 同包其他类:直接 new 使用,无需import;
  • 不同包类:通过 import 完整包名.类名 导入后,实例化、继承、调用方法全部正常;

示例:

包1 com.entity.User.java

java 复制代码
package com.entity;
public class User{}

包2 com.test.Test.java

java 复制代码
package com.test;
import com.entity.User;
public class Test{
    public static void main(String[] args) {
        User user = new User(); // 跨包正常使用
    }
}

2. 缺省class

权限:仅当前同一个package包内可见

  • 同包类:正常创建对象、调用;
  • 跨包类:就算手动import导入,也无法实例化、继承,直接编译报错;

示例:

包1 com.entity.Order.java

java 复制代码
package com.entity;
// 缺省类,仅限com.entity包内使用
class Order{}

包2无法使用Order,代码直接报错。

三、编译后生成class文件规则

Java编译机制:每个独立顶层类,都会单独生成一份 .class 字节码文件

  1. 文件内 public class Student → 生成 Student.class
  2. 文件内缺省类 Temp → 生成 Temp.class

Student.java

java 复制代码
public class Student{}
class Helper{}

编译产出两个文件:Student.classHelper.class

两种类在编译产物上无区别,只是权限与文件约束不同。

四、继承、重写使用限制

  1. public class
    任意包的类都可以 extends 该类作为父类,支持跨包继承、多态;
  2. 缺省class
    只有同包下的类能继承,其他包无法继承该类,不能跨包做父类。

五、程序入口main方法适配

  1. public class
    public static void main(String[] args)写在public类中,直接执行 java 类名,是行业标准规范;
  2. 缺省class
    main方法可以写在缺省类里,运行不会报错,但不推荐。
    原因:其他包无法访问该类,项目分层后不方便调用启动程序。

六、框架反射适配场景

Spring、MyBatis等主流框架会通过反射跨包创建类对象:

  1. Controller、Service、Mapper、实体类必须是 public class
  2. 如果写成缺省class,框架跨包反射实例化失败,抛出异常。

七、适用开发场景区分

使用 public class 的场景

  1. 项目对外提供的实体类、工具类、业务类;
  2. 程序启动类(包含main主方法);
  3. 需要跨包继承、被多处调用的父类;
  4. 框架注解类(@Controller、@Service等);
  5. 需要给第三方模块、其他项目调用的公共API类。

使用缺省class的场景

  1. 仅当前包内部使用的辅助工具类;
  2. 临时工具类,不需要对外暴露;
  3. 测试专用辅助类,仅本包单元测试调用;
  4. 不希望外部包访问、隐藏内部逻辑。

八、完整对比表格

对比维度 public class 缺省class(无修饰符)
访问权限 所有包全局可见 仅同一个包内可见
单文件数量 最多1个 不限数量
类名与文件名 必须完全一致 无任何要求
跨包访问 import后正常使用 跨包直接编译报错
跨包继承 支持 不支持
框架反射调用 正常实例化 反射失败报错
工程规范 对外业务类标准写法 包内隐藏辅助类专用

九、高频易错点总结

  1. 只有顶层类区分public/缺省,方法内的内部类不受文件名规则限制;
  2. private、protected不能修饰顶层类,只能修饰成员变量、方法、内部类;
  3. 缺省权限没有关键字,不要写成default(default仅用于接口方法、switch分支);
  4. 多人协作项目尽量遵循:一个文件一个public类,不要大量缺省类堆在同一个文件。