Eclipse中继承自Collection<Object>的示例

1. 前言

1.1 起因

在使用Eclipse进行调试时,发现某个对象的下面只显示对象的逻辑内容而不显示属性。如下图所示,myCollection对象只显示逻辑内容而不显示这些内容保存在哪个属性中。

1.2 寻因

在查询相关资料后,发现是与其实现了某些容器类接口有关,相关资料如下:
Show Logical Structure 在 Eclipse 中的显示行为与类是否实现了 Collection<E>Map<K,V> 接口密切相关。Eclipse 调试器对于集合类(如 ListSetMap)有特殊的处理逻辑。

1.3 Show Logical StructureCollection<E> 的关系

  1. 集合类的特殊处理

    当一个类实现了 Collection<E> 接口(或其子接口,如 ListSet)或者实现了 Map<K,V> 接口,Eclipse 调试器会专门处理这些类,以便显示集合的内容,而不是对象的具体字段(属性)。Show Logical Structure 的目的是简化查看这些集合中的元素,而不是展示整个对象的结构。

  2. 逻辑结构显示规则

    • 对于实现 Collection<E> 接口的类Show Logical Structure 会显示集合中的元素,而不是类的属性。即使类还有其他属性,它们也可能被 Eclipse 忽略,显示的主要是集合的逻辑内容。
    • 对于实现 Map<K,V> 的类 :同样的,Show Logical Structure 会聚焦于键值对的内容,而不是 Map 对象的其他属性或元数据。
  3. 普通类的处理

    对于没有实现 Collection<E>Map<K,V> 接口的普通类,Eclipse 不会做这种特殊处理。按下 Show Logical Structure 后,Eclipse 仍然会显示该类的所有字段(属性)的名称和值,不会将其内容作为集合结构来显示。

1.4 实现 Collection<E>Map<K,V> 会影响 Eclipse 显示:

当类实现了 Collection<E>Map<K,V> 时,调试器会:

  • 优先显示集合的元素,而不是类的字段名称。
  • 忽略非集合的字段,并直接展示集合内部的逻辑结构(如 List 的元素或 Map 的键值对)。

1.5 示例

假设有一个类 MyList,它继承了 ArrayList

java 复制代码
import java.util.ArrayList;

public class MyList<E> extends ArrayList<E> {
    private String metadata;

    public MyList(String metadata) {
        this.metadata = metadata;
    }

    public String getMetadata() {
        return metadata;
    }
}

如果你调试一个 MyList 对象,并按下 Show Logical Structure 按钮,Eclipse 调试器会专注于显示 ArrayList 的元素,而不会展示 metadata 属性。即使 metadata 存在,调试面板中也会忽略它,只显示集合元素。

同样的道理,任何实现了 Collection<E> 接口的类,在调试时 Eclipse 都会默认展示集合的内容,而不显示其他属性。

1.6 如果不实现 Collection<E>

如果类没有实现 Collection<E>,即使它内部有 ListMap 类型的字段,按下 Show Logical Structure 时,Eclipse 仍然会显示类的所有字段及其名称。这时,调试器不会做集合类的特殊处理,依旧会展示属性名和值。

1.7 结论:

  • 实现 Collection<E>Map<K,V> 接口的类,在按下 Show Logical Structure 后,Eclipse 会专注于显示集合内部的元素,而忽略其他字段。
  • 如果不希望 Eclipse 在调试时显示某些字段,可以利用这一特性,通过继承集合类或实现集合接口来控制调试器的显示逻辑。

好的,下面是一个完整的示例,展示如何创建一个自定义集合类,继承自 Collection<Object>。在这个示例中,我们将实现基本的集合功能,并且当在 Eclipse 中按下 Show Logical Structure 时,将优先显示集合中的元素。

2 完整代码示例

2.1 创建 MyCollection

该类实现了 Collection<Object> 接口,并提供了必要的方法。

java 复制代码
import java.util.Iterator;
import java.util.NoSuchElementException;

public class MyCollection implements Collection<Object> {
    private Object[] elements;
    private int size;
    private static final int INITIAL_CAPACITY = 10;

    public MyCollection() {
        elements = new Object[INITIAL_CAPACITY];  // 初始化数组
        size = 0;
    }

    @Override
    public boolean add(Object e) {
        if (size >= elements.length) {
            resize();  // 如果数组满了,扩展容量
        }
        elements[size++] = e;  // 添加元素
        return true;
    }

    private void resize() {
        Object[] newArray = new Object[elements.length * 2];
        System.arraycopy(elements, 0, newArray, 0, elements.length);
        elements = newArray;  // 更新数组
    }

    @Override
    public boolean remove(Object o) {
        for (int i = 0; i < size; i++) {
            if (elements[i].equals(o)) {
                System.arraycopy(elements, i + 1, elements, i, size - i - 1);
                elements[--size] = null;  // 清理最后一个元素
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;  // 判断是否为空
    }

    @Override
    public int size() {
        return size;  // 返回大小
    }

    @Override
    public Iterator<Object> iterator() {
        return new Iterator<Object>() {
            private int currentIndex = 0;

            @Override
            public boolean hasNext() {
                return currentIndex < size;  // 判断是否有下一个元素
            }

            @Override
            public Object next() {
                if (!hasNext()) {
                    throw new NoSuchElementException();  // 如果没有下一个元素,抛出异常
                }
                return elements[currentIndex++];  // 返回当前元素并递增索引
            }
        };
    }

    @Override
    public Object[] toArray() {
        Object[] array = new Object[size];
        System.arraycopy(elements, 0, array, 0, size);  // 返回当前数组的副本
        return array;
    }

    @Override
    public <T> T[] toArray(T[] a) {
        if (a.length < size) {
            return (T[]) toArray();  // 返回新数组
        }
        System.arraycopy(elements, 0, a, 0, size);  // 复制到传入的数组
        if (a.length > size) {
            a[size] = null;  // 清理多余元素
        }
        return a;
    }

    @Override
    public boolean contains(Object o) {
        for (int i = 0; i < size; i++) {
            if (elements[i].equals(o)) {
                return true;  // 找到元素返回 true
            }
        }
        return false;  // 未找到元素返回 false
    }

    @Override
    public boolean addAll(Collection<? extends Object> c) {
        boolean modified = false;
        for (Object e : c) {
            if (add(e)) {
                modified = true;  // 如果添加成功,标记为修改
            }
        }
        return modified;  // 返回是否有修改
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        for (Object e : c) {
            if (!contains(e)) {
                return false;  // 如果有未包含的元素,返回 false
            }
        }
        return true;  // 所有元素均被包含
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        boolean modified = false;
        for (Object e : c) {
            if (remove(e)) {
                modified = true;  // 如果移除成功,标记为修改
            }
        }
        return modified;  // 返回是否有修改
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        boolean modified = false;
        for (int i = 0; i < size; i++) {
            if (!c.contains(elements[i])) {
                remove(elements[i]);  // 只保留包含的元素
                modified = true;  // 标记为修改
                i--;  // 调整索引
            }
        }
        return modified;  // 返回是否有修改
    }

    @Override
    public void clear() {
        for (int i = 0; i < size; i++) {
            elements[i] = null;  // 清理所有元素
        }
        size = 0;  // 重置大小
    }
    
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < size; i++) {
            sb.append(elements[i]);
            if (i < size - 1) {
                sb.append(", ");  // 添加逗号
            }
        }
        sb.append("]");
        return sb.toString();  // 返回字符串表示
    }
}
2.2 创建一个简单的 Main 类来测试

这个类将创建 MyCollection 实例,并添加一些元素。

java 复制代码
public class Main {
    public static void main(String[] args) {
        // 创建 MyCollection 实例
        MyCollection myCollection = new MyCollection();

        // 添加元素到集合
        myCollection.add("Item 1");
        myCollection.add("Item 2");
        myCollection.add("Item 3");

        // 打印 MyCollection 对象
        System.out.println(myCollection);

        // 在此处设置断点,使用 Eclipse 调试功能中的 "Show Logical Structure" 查看 myCollection 的内容
    }
}

2.3 调试过程

  1. 设置断点 :在 System.out.println(myCollection); 这行代码上设置一个断点。
  2. 运行调试:启动调试模式。
  3. 按下 Show Logical Structure
    • 在调试时,展开 myCollection 对象,你应该看到它的元素("Item 1"、"Item 2"、"Item 3")被展示,而 MyCollection 的其他属性将不会出现在显示中。

2.4 输出示例

  • 在控制台输出

    复制代码
    [Item 1, Item 2, Item 3]
  • 在调试面板中(按下 Show Logical Structure 后)

    复制代码
    Item 1
    Item 2
    Item 3

2.5 总结

在这个示例中,由于 MyCollection 实现了 Collection<Object> 接口,因此在调试时,Eclipse 会优先显示集合中的元素,而不显示其他属性。这样可以有效地控制调试输出,专注于集合的逻辑内容。

相关推荐
CodeAmaz1 分钟前
Spring编程式事务详解
java·数据库·spring
没有bug.的程序员3 分钟前
微服务基础设施清单:必须、应该、可以、无需的四级分类指南
java·jvm·微服务·云原生·容器·架构
武子康6 分钟前
Java-204 RabbitMQ Connection/Channel 工作流程:AMQP 发布消费、抓包帧结构与常见坑
java·分布式·消息队列·rabbitmq·ruby·java-activemq
郑州光合科技余经理7 分钟前
海外国际版同城服务系统开发:PHP技术栈
java·大数据·开发语言·前端·人工智能·架构·php
appearappear18 分钟前
Mac 上重新安装了Cursor 2.2.30,重新配置 springboot 过程记录
java·spring boot·后端
CryptoRzz26 分钟前
日本股票 API 对接实战指南(实时行情与 IPO 专题)
java·开发语言·python·区块链·maven
程序员水自流29 分钟前
MySQL数据库自带系统数据库功能介绍
java·数据库·mysql·oracle
谷哥的小弟33 分钟前
Spring Framework源码解析——RequestContext
java·后端·spring·框架·源码
天远Date Lab39 分钟前
Java微服务实战:聚合型“全能小微企业报告”接口的调用与数据清洗
java·大数据·python·微服务
lizz3144 分钟前
C++操作符重载深度解析
java·c++·算法