Java-面向对象-包、反射

什么是包(Package)?

包的分类

内置包(Java API)

用户自定义包

包的命名规则

使用包(import)

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

什么是反射?

反射能干什么

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

反射的常见用法

获取Class对象的三种方式

 获取类名、包名、父类、接口

获取字段 并访问私有字段

获取方法并调用

获取构造器并创建对象

反射的缺点


什么是包(Package)?

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

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:网络编程相关类

  • 用户自定义包

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

package myapp.utils;

public class Helper {
    // 辅助方法
}

包的命名规则

  • 通常以反域名的方式命名,如:com.example.project

  • 使用小写字母

  • 避免使用Java的保留字

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

假设我写了一个类:

package com.example.utils;

public class Tool {
    // 工具类
}

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

项目目录/
└── com/
    └── example/
        └── utils/
            └── Tool.java

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

com/
└── example/
    └── utils/
        └── Tool.class

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

Tool.java:1: 错误: 程序包 com.example.utils 不存在
package com.example.utils;

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

使用包(import)

  • 导入单个类
import java.util.ArrayList;
  • 导入整个包
import java.util.*;
  • 无需导入的包

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

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

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

/* 文件名: Animal.java */
package animals;
 
interface Animal {
   public void eat();
   public void travel();
}

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

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对象的三种方式

// 方法1:通过类名.class
Class<?> clazz1 = Person.class;

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

// 方法3:通过全类名
Class<?> clazz3 = Class.forName("com.example.Person");
  •  获取类名、包名、父类、接口

System.out.println(clazz1.getName()); // 类的全名
System.out.println(clazz1.getPackage()); // 包
System.out.println(clazz1.getSuperclass()); // 父类
System.out.println(Arrays.toString(clazz1.getInterfaces())); // 实现的接口
  • 获取字段 并访问私有字段

Field field = clazz1.getDeclaredField("name");
field.setAccessible(true); // 关闭访问检查
field.set(p, "张三"); // 给 p 的 name 字段赋值
System.out.println(field.get(p)); // 获取 p 的 name 字段
  • 获取方法并调用

Method method = clazz1.getDeclaredMethod("sayHello", String.class);
method.setAccessible(true); // 可访问私有方法
method.invoke(p, "小明"); // 调用方法,参数是对象和实际参数
  • 获取构造器并创建对象

Constructor<?> constructor = clazz1.getConstructor(String.class, int.class);
Object obj = constructor.newInstance("李四", 25);

反射的缺点

  • 性能较低:反射涉及大量的运行时操作,性能开销比直接代码大

  • 安全问题:可以访问私有字段,破坏封装。

  • 不易维护:反射代码可读性差,易出错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值