具体来说,我正在尝试这段代码:
package hello;
public class Hello {
Clock clock = new Clock();
public static void main(String args[]) {
clock.sayTime();
}
}
Run Code Online (Sandbox Code Playgroud)
但它给出了错误
无法访问静态方法main中的非静态字段
所以我把声明改为clock:
static Clock clock = new Clock();
Run Code Online (Sandbox Code Playgroud)
它奏效了.在声明之前放置该关键字是什么意思?对于该对象可以做什么,它究竟会做什么和/或限制什么?
我的问题是静态关键字的一个特定用法.可以使用static关键字来覆盖不属于任何函数的类中的代码块.例如,以下代码编译:
public class Test {
private static final int a;
static {
a = 5;
doSomething(a);
}
private static int doSomething(int x) {
return (x+5);
}
}
Run Code Online (Sandbox Code Playgroud)
如果你删除static它抱怨的关键字,因为变量a是final.但是,可以删除两个final和static关键字并使其编译.
这两种方式让我感到困惑.我怎么能有一个不属于任何方法的代码部分?如何调用它?一般来说,这种用法的目的是什么?或者更好,我在哪里可以找到关于此的文档?
据我所知,"静态初始化块"用于设置静态字段的值,如果不能在一行中完成的话.
但我不明白为什么我们需要一个特殊的块.例如,我们将一个字段声明为静态(没有值赋值).然后编写几行代码,生成并为上面声明的静态字段赋值.
为什么我们需要在一个特殊的块这样的行这样的:static {...}?
java static initialization static-block initialization-block
我正在使用静态代码块来初始化我所拥有的注册表中的某些控制器.因此,我的问题是,我可以保证这个静态代码块只在首次加载类时才会被调用一次吗?我知道我无法保证何时会调用此代码块,我猜它是在Classloader首次加载它时.我意识到我可以在静态代码块中同步类,但我的猜测实际上这是怎么回事?
简单的代码示例是;
class FooRegistry {
static {
//this code must only ever be called once
addController(new FooControllerImpl());
}
private static void addController(IFooController controller) {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
或者我应该这样做;
class FooRegistry {
static {
synchronized(FooRegistry.class) {
addController(new FooControllerImpl());
}
}
private static void addController(IFooController controller) {
// ...
}
}
Run Code Online (Sandbox Code Playgroud) java static multithreading synchronization static-initializer
所以我最近一直在研究我的Java技能,并且发现了一些我之前不知道的功能.静态和实例初始化器是两种这样的技术.
我的问题是什么时候会使用初始化程序而不是在构造函数中包含代码?我想到了几个明显的可能性:
static/instance initializers可用于设置"final"静态/实例变量的值,而构造函数则不能
静态初始化程序可用于设置类中任何静态变量的值,这应该比在每个构造函数的开头具有"if(someStaticVar == null)// do stuff"代码块更有效
这两种情况都假设设置这些变量所需的代码比简单的"var = value"更复杂,否则似乎没有任何理由使用初始化器而不是在声明变量时简单地设置值.
然而,虽然这些并非微不足道的收益(特别是设置最终变量的能力),但似乎应该使用初始化程序的情况相当有限.
当然可以在构造函数中使用初始化器来完成很多工作,但我真的没有看到这样做的原因.即使一个类的所有构造函数共享大量代码,使用私有initialize()函数似乎比使用初始化程序更有意义,因为它不会阻止您在编写新代码时运行该代码构造函数.
我错过了什么吗?是否还有许多其他情况需要使用初始化程序?或者它是否真的只是在非常具体的情况下使用的相当有限的工具?
java constructor initializer static-initializer initialization-block
我正面临一个用例,我想声明一个static final带有初始化语句的字段,该语句被声明为抛出一个已检查的异常.通常,它看起来像这样:
public static final ObjectName OBJECT_NAME = new ObjectName("foo:type=bar");
我在这里遇到的问题是ObjectName构造函数可能会抛出各种已检查的异常,我并不关心这些异常(因为我知道我的名字是有效的,如果它没有崩溃就会崩溃).java编译器不会让我忽略它(因为它是一个经过检查的异常),我宁愿不诉诸:
public static final ObjectName OBJECT_NAME;
static{
try{
OBJECT_NAME = new ObjectName("foo:type=bar");
}catch(final Exception ex){
throw new RuntimeException("Failed to create ObjectName instance in static block.",ex);
}
}
因为静态块确实非常难以阅读.有没有人有一个关于如何以一个漂亮,干净的方式处理这种情况的建议?
这不是一个"问题"所以我正在制作CW.
该
assert
Run Code Online (Sandbox Code Playgroud)
关键字很棒!
它应该让你觉得你的自己对你编写的代码更有信心,但是,直到今天,当我创建一个小型测试类(<20行)时,我意识到自从它被引入以来从未使用它.
哎呀!我几乎没有使用记录器,这确实非常有用,但直到今天我才意识到我不使用断言.
你使用断言吗?如果不是,那是什么原因?
我有这个代码
private static Set<String> myField;
static {
myField = new HashSet<String>();
myField.add("test");
}
Run Code Online (Sandbox Code Playgroud)
它的工作原理.但是当我翻转订单时,我收到了非法的前向引用错误.
static {
myField = new HashSet<String>();
myField.add("test"); // illegal forward reference
}
private static Set<String> myField;
Run Code Online (Sandbox Code Playgroud)
我有点震惊,我没想到Java这样的东西.:)
这里发生了什么?为什么声明的顺序很重要?为什么分配工作而不是方法调用?
java ×8
static ×5
initializer ×2
assert ×1
assertions ×1
constructor ×1
exception ×1
final ×1
oop ×1
restriction ×1
static-block ×1