首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Java-面向对象-包、反射

Java-面向对象-包、反射

作者头像
小陈又菜
发布2025-12-23 16:20:53
发布2025-12-23 16:20:53
980
举报

什么是包(Package)?

包是Java中一种逻辑分组机制,类似于一个文件夹。Java中的类、接口都可以放在包中,多个相关的类/接口可以放在同一个包里。

代码语言:javascript
复制
package com.example.student;

public class Student {
    // 类的实现
}

如,上面的student类就属于com.example.student包。

包的分类

  • 内置包(Java API)
  1. java.lang:基本类,如 StringMathObject(默认导入)
  2. java.util:集合框架、日期、工具类
  3. java.io:输入输出相关类
  4. java.net:网络编程相关类
  • 用户自定义包

可以自己创建包,讲类组织起来:

代码语言:javascript
复制
package myapp.utils;

public class Helper {
    // 辅助方法
}

包的命名规则

  • 通常以反域名的方式命名,如:com.example.project
  • 使用小写字母
  • 避免使用Java的保留字

注意:Java源文件的包名,一定要和文件的目录结构保持一致!!!

假设我写了一个类:

代码语言:javascript
复制
package com.example.utils;

public class Tool {
    // 工具类
}

那么它的文件就必须放在下面目录结构中:

代码语言:javascript
复制
项目目录/
└── com/
    └── example/
        └── utils/
            └── Tool.java

当javac Tool.java被编译后的字节码Tool.class也会被放在:

代码语言:javascript
复制
com/
└── example/
    └── utils/
        └── Tool.class

如果你把上面的 Tool.java 放在根目录下,而它的包名还是 com.example.utils,那么编译时就会报错:

代码语言:javascript
复制
Tool.java:1: 错误: 程序包 com.example.utils 不存在
package com.example.utils;

除非你自己用命令行指定好 classpath 和目录结构,但一般来说,目录结构必须与包名完全对应。

使用包(import)

  • 导入单个类
代码语言:javascript
复制
import java.util.ArrayList;
  • 导入整个包
代码语言:javascript
复制
import java.util.*;
  • 无需导入的包

java.lang 包是默认导入的,比如 String, System, Math 等类可以直接使用。

如何创建和使用自定义的包

在 animals 包中加入一个接口(interface):

代码语言:javascript
复制
/* 文件名: Animal.java */
package animals;
 
interface Animal {
   public void eat();
   public void travel();
}

在同一个包中加入该接口的实现:

代码语言:javascript
复制
package animals;
 
/* 文件名 : MammalInt.java */
public class MammalInt implements Animal{
 
   public void eat(){
      System.out.println("Mammal eats");
   }
 
   public void travel(){
      System.out.println("Mammal travels");
   } 
 
   public int noOfLegs(){
      return 0;
   }
 
   public static void main(String args[]){
      MammalInt m = new MammalInt();
      m.eat();
      m.travel();
   }
}

什么是反射?

反射是 Java 提供的一种机制,它允许程序在运行时查看和操作类的结构。

反射能干什么

功能

说明

获取类的信息

包括类名、包名、继承关系、修饰符等

获取成员

字段(Field)、方法(Method)、构造器(Constructor)

动态创建对象

通过构造器或无参构造方法创建

动态调用方法

运行时决定调用哪个方法

修改字段值

哪怕是私有字段,也能访问和修改

反射的核心类(都在 java.lang.reflectjava.lang 包中)

类/接口

用途

Class<T>

表示类或接口本身,是反射的入口

Field

表示类中的字段(成员变量)

Method

表示类中的方法

Constructor

表示类中的构造函数

Modifier

提供修饰符信息,如 public/private

反射的常见用法

  • 获取Class对象的三种方式
代码语言:javascript
复制
// 方法1:通过类名.class
Class<?> clazz1 = Person.class;

// 方法2:通过对象实例
Person p = new Person();
Class<?> clazz2 = p.getClass();

// 方法3:通过全类名
Class<?> clazz3 = Class.forName("com.example.Person");
  • 获取类名、包名、父类、接口
代码语言:javascript
复制
System.out.println(clazz1.getName()); // 类的全名
System.out.println(clazz1.getPackage()); // 包
System.out.println(clazz1.getSuperclass()); // 父类
System.out.println(Arrays.toString(clazz1.getInterfaces())); // 实现的接口
  • 获取字段 并访问私有字段
代码语言:javascript
复制
Field field = clazz1.getDeclaredField("name");
field.setAccessible(true); // 关闭访问检查
field.set(p, "张三"); // 给 p 的 name 字段赋值
System.out.println(field.get(p)); // 获取 p 的 name 字段
  • 获取方法并调用
代码语言:javascript
复制
Method method = clazz1.getDeclaredMethod("sayHello", String.class);
method.setAccessible(true); // 可访问私有方法
method.invoke(p, "小明"); // 调用方法,参数是对象和实际参数
  • 获取构造器并创建对象
代码语言:javascript
复制
Constructor<?> constructor = clazz1.getConstructor(String.class, int.class);
Object obj = constructor.newInstance("李四", 25);

反射的缺点

  • 性能较低:反射涉及大量的运行时操作,性能开销比直接代码大
  • 安全问题:可以访问私有字段,破坏封装。
  • 不易维护:反射代码可读性差,易出错。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-04-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是包(Package)?
  • 包的分类
  • 包的命名规则
  • 使用包(import)
  • 如何创建和使用自定义的包
  • 什么是反射?
  • 反射能干什么
  • 反射的核心类(都在 java.lang.reflect 和 java.lang 包中)
  • 反射的常见用法
  • 反射的缺点
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档