如何强制所有 Java 类具有属性

Posted

技术标签:

【中文标题】如何强制所有 Java 类具有属性【英文标题】:How to force all Java classes to have a attribute 【发布时间】:2011-08-01 06:37:20 【问题描述】:

我希望所有 Java 类都有一个 logger 变量:

private static final Logger logger = Logger.getLogger(Foo.class);

但我必须在所有课程中输入这一行。

有没有办法自动化这个?注释可以帮助我吗?

【问题讨论】:

与***.com/questions/2154726相关...不要关注那个问题的反对者。我们有几个人在做日志行的剪切粘贴并且忘记更改类名,因此我们需要一种快速的方法来找到这些损坏的初始化。效果很好。请注意,默认情况下,您可能还希望 equalshashCode 抛出异常,因为除了最简单的情况(无继承)之外,它们会被破坏但这里的人不太可能同意(我建议他们去与 Joshua Bloch 和 Effective Java 争论)。 这正是昨天代码审查中发生的事情! 【参考方案1】:

我猜你真正想要的不是继承。事实上,继承是合并记录器恕我直言的一种相当糟糕的方式,因为记录器并不是真正的类功能,而是应用程序的cross-cutting concern。 您需要的是一个经过调整的新类模板。如果你使用的是eclipse,可以在Java->Code Style->Code Templates下的Preferences中找到,然后切换到对话框的右侧,选择代码->新建Java文件在intellij idea中,您可以在文件->设置->文件模板->类下找到模板 对this question 的接受回答展示了将 log4j 日志记录合并到模板中,并带有 import 语句。

【讨论】:

所以,您是说没有 Java 方法可以做到这一点。我需要 IDE 的帮助 java中有很多方法。问题不是你能做什么,而是你应该做什么。你可以通过多种方式实现通用日志记录——继承、反射、作为一个方面,或者使用代码模板、键盘快捷键甚至 DSL……如果你真的想要的话 您可以将代码模板视为一种非侵入性方式,不会强制您的应用程序使用其他框架或库或不良编码实践【参考方案2】:

如果您想采用继承方式,恕我直言,这不是很好,您可以从抽象基类继承,其中声明受保护的非静态 Logger 如下:

protected final Logger log = Logger.getLogger(getClass().getName());

这样,记录器的类将属于实现类。但是当然,Java 只允许单继承存在问题,当您需要扩展另一个类时,这可能会给您带来麻烦。

我个人正在使用 AOP(面向方面​​编程)进行日志记录,但这并不总是一种解决方案。

【讨论】:

【参考方案3】:

如果您使用的是 Eclipse,请为 Java 类创建一个新的代码模板。这将在每个新类中添加一个记录器引用,包括适当的导入。如果您不是在谈论 log4j,请调整导入。

然后

【讨论】:

【参考方案4】:

有没有办法自动化这个?

当然不是纯 Java。

继承不能解决这个问题......如果你想要一个static 和/或private 的字段。最接近的方法是将这样的方法添加到基类中:

    protected final Logger getLogger() 
        return Logger.getLogger(this.getClass());
    

而且那会相当昂贵。

或者,您可以将非私有、非静态字段添加到基类;例如

    protected final Logger log = Logger.getLogger(this.getClass());

或者您可以让您的 IDE 或一些源代码处理器/生成器在每个类的源代码中添加一个 static private Logger 字段。

注释可以帮助我吗?

我不这么认为。您可能能够使用 AOP 注入字段,但我认为您的代码无法引用它。

【讨论】:

但我认为您的代码无法引用它 如果您只使用 aspectj 编译器,它会起作用。但是如果你用 javac 编译然后编织类是不可能的。 我就是这么想的。我们实际上是在谈论一种不同的编程语言......【参考方案5】:

使用继承

继承可能对你有帮助

【讨论】:

【参考方案6】:

嗯, 您可以做的是创建一个拥有此记录器变量的抽象父类,并且您的每个类都继承自该类。 但是在java中只允许一个继承,你可能会遇到麻烦,因为继承被你的父类阻止了。

第二个问题是:logger 总是会用抽象父类的类来初始化。如果这不打扰你....

【讨论】:

【参考方案7】:

学习依赖注入,使用Seam(包括Weld)、Spring或Guice等框架,然后使用面向方面编程(AOP)自动记录所有调用方法(以及该方法需要多长时间)。

在某些情况下,您仍然希望定义 Logger 并在某些方法中进行一些日志记录,但 AOP 方法仍然会删除许多违反 DRY(不要重复自己)原则的样板代码.

【讨论】:

【参考方案8】:

一个非常原始的解决方案是创建一个包含要添加到所有类的属性的抽象类。 但是由于 java 不支持多重继承,如果您需要从其他类继承,则此解决方案不适合。 据我所知,注解并非旨在提供此类功能。

【讨论】:

【参考方案9】:

不要这样做,这是过度设计。只需在每个需要记录的类中放置一个单独的记录器并完成它。

作为一个小技巧,您可以省略“私有”(使记录器包受到保护)以避免在当前没有使用记录器的代码行时出现讨厌的 Eclipse“未使用”警告,而无需添加 SuppressWarnings 注释.

【讨论】:

【参考方案10】:

您的类应该从一个公共基类继承它。

我不是 Java 大师,但应该可以做到这一点

public class Vehicle

    protected Logger logger = Logger.getLogger(this.getClass());


public class Car extends Vehicle


这就是它可以在 C# 中完成的方式 - 自从我上次使用 Java 以来已经有很多年了。

【讨论】:

这是不可能的,因为每个类 logger 应该不同(即 BaseClass 应该使用 Logger.getLogger(BaseClass.class)ExtendsBase 应该使用 LOgger.getLogger(ExtendsBase.class))。 但在其中一个类中,他需要扩展另一个类,则上述过程失败。由于java不支持多重继承 这不是 100% 的答案 您不能从静态上下文中引用this。而且没有功能typeof @Joachim 整个问题看起来像是在解决一个严重缺陷的设计。

以上是关于如何强制所有 Java 类具有属性的主要内容,如果未能解决你的问题,请参考以下文章

强制在来自 NET Web 服务代理类的 SOAP 请求中包含默认值属性属性

我可以强制 Angular 组件的所有实例都具有属性吗?

强制类/方法的属性修饰

查找具有特定属性的所有类

java反射机制

如何通过使用接口或抽象来确保类具有静态属性?