标签: static-initializer

加载,链接和初始化 - 何时加载类?

我对类加载的理解是一个类在第一次需要时被加载(以非常简单的方式放置).使用-verbose:class和Iterators类的修改版本运行以下示例,该类在调用其clinit时打印消息我观察到了一些我无法解释的内容:

public class IteratorsTest
{
    public static void main(String[] args)
    {
        com.google.common.collect.Iterators.forArray(1, 2, 3);
    }
}
Run Code Online (Sandbox Code Playgroud)

(清理)输出如下:

[Loaded com.google.common.collect.Iterators from file:...]
[Loaded com.google.common.collect.Iterators$1 from file:...]
---------> Iterators <clinit>
Run Code Online (Sandbox Code Playgroud)

为什么在调用clinit之前加载Iterators $ 1?它只在临床中定义,不是吗?

  static final UnmodifiableListIterator<Object> EMPTY_LIST_ITERATOR =
      new UnmodifiableListIterator<Object>() {
  ...
  }
Run Code Online (Sandbox Code Playgroud)

这导致以下字节代码:

static <clinit>()V
   L0
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    LDC "---------> Iterators clinit --------------"**
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
   L1
    NEW com/google/common/collect/Iterators$1
    DUP
    INVOKESPECIAL com/google/common/collect/Iterators$1.<init> ()V
   L2
    PUTSTATIC com/google/common/collect/Iterators.EMPTY_LIST_ITERATOR : Lcom/google/common/collect/UnmodifiableListIterator;
Run Code Online (Sandbox Code Playgroud)

为了让我更加困惑,我还有一个样本(太复杂了,无法在此处发布),其中与上面主要内容相同的代码行导致以下输出:

[Loaded com.google.common.collect.Iterators from file:...]
---------> Iterators <clinit>
[Loaded com.google.common.collect.Iterators$1 from …
Run Code Online (Sandbox Code Playgroud)

java jvm bytecode classloader static-initializer

7
推荐指数
2
解决办法
1075
查看次数

Java:什么是static {}?

有人可以解释一下以下是什么吗?

public class Stuff
{
    static
    {
        try
        {
            Class.forName("com.mysql.jdbc.Driver");
        }
        catch ( ClassNotFoundException exception )
        {
            log.error( "ClassNotFoundException " + exception.getMessage( ) );
        }
...
}
Run Code Online (Sandbox Code Playgroud)

这静态{...}做了什么?

我知道来自C++的静态变量,但这是一个静态块还是什么?

什么时候这个东西会被执行?

java static-initializer

6
推荐指数
2
解决办法
510
查看次数

Java基础知识:没有名称或返回类型的静态函数

public class Main {
    public static final Logger LOGGER = Logger.getLogger(Main.class.getName());

    static {
        try {
             LOGGER.addHandler(new FileHandler("errors.log",true));
        }
        catch(IOException ex) {
             LOGGER.log(Level.WARNING,ex.toString(),ex);
        }
    }
...
Run Code Online (Sandbox Code Playgroud)

我想知道这个无名静态功能是什么.

我在java(我目前正在学习)中从未见过这样的东西.

它是为了什么?

什么时候通常使用?

什么时候会在程序中执行?

java static function static-initializer

6
推荐指数
1
解决办法
2201
查看次数

内置类型的对象是否具有特殊的静态初始化顺序优先级?

我预计以下代码会产生分段错误(或其他UB):

struct T {
   T();
};

T t;
char const* str = "Test string";

T::T() {
   std::cout << str; // zero-initialised, only!
}

int main() {}
Run Code Online (Sandbox Code Playgroud)

那是因为t之前已经初始化了str.我期望由于零初始化而str保持该值(char const*)0.我的解释[C++11: 3.6.2/2]支持这一点.

但是,上面的代码片段似乎按预期输出了字符串(我也通过打印指针的值来确认行为).

我是否缺少一些静态初始化规则,允许strt开始构建之前进行值初始化?标准在哪里?


在构建时出现了静态变量解析,其中一个回答者断言使用char const*而不是std::string静态全局避免了静态初始化顺序惨败.我不同意,但现在我不太确定......

c++ static-initializer

6
推荐指数
2
解决办法
239
查看次数

如果在声明之前放置静态初始化程序错误

我注意到静态初始化器中的某些内容可能是javac中的一个错误.我构建了一个场景,我可以为变量赋值,但不能读回该值.

下面是两个示例,第一个编译正常,第二个在尝试从tmp读取值时出错,但由于某种原因,允许为tmp分配值.我可以理解它是否既不能读取也不能写入变量,因为tmp是在静态初始化器之后声明的,但是只有其中一个错误对我来说没有意义.

//Compiles Successfully:
public class Script
{
    public static Object tmp;
    static
    {
        tmp = new Object();
        System.out.println(tmp);
    }

}

//error only on the read but not the assignment
public class Script
{

    static
    {
        tmp = new Object();
        System.out.println(tmp);
    }
    public static Object tmp;
}
Run Code Online (Sandbox Code Playgroud)

为了进一步强调这一点,这确实可以成功编译.

public class Script
{

    static
    {
        tmp = new Object();
    }
    public static Object tmp;
}
Run Code Online (Sandbox Code Playgroud)

java static-initializer

6
推荐指数
1
解决办法
128
查看次数

Java静态初始化程序可以调用静态方法吗?

我可以从Java中的静态初始化程序调用静态方法吗?以下是否有效并保证按照Java规范工作?

public class Foo {

  private final static int bar;

  private static int generateValue() {
    return 123;
  }

  static {
    bar = generateValue();
  }

}
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,我可能期望bar在里面可用generateValue().我知道静态初始化程序块的顺序很重要,但我没有听说静态方法声明的顺序很重要.但是,在执行静态初始化程序块之前,静态方法是否可用?

java static-methods static-initializer

6
推荐指数
1
解决办法
1451
查看次数

再次调用静态初始化程序

一旦加载了类,有没有办法再次调用静态初始值设定项?

public class Foo {

    static {
        System.out.println("bar");
    }

}
Run Code Online (Sandbox Code Playgroud)

编辑:

我需要调用静态初始化程序,因为我没有编写原始类,我需要调用的逻辑是在静态初始化程序中实现的.

java static static-initializer

5
推荐指数
2
解决办法
4185
查看次数

我可以保证在Java中运行静态初始化器的顺序吗?

我有一个Set类(这是J2ME,所以我对标准API的访问权限有限;只是为了解释我明显的轮子改造).我正在使用我的set类在类和子类中创建常量集.它看起来像这样......

class ParentClass
{
    protected final static Set THE_SET = new Set() {{
        add("one");
        add("two");
        add("three");
    }};
}


class SubClass extends ParentClass
{
    protected final static Set THE_SET = new Set() {{
        add("four");
        add("five");
        add("six");
        union(ParentClass.THE_SET); /* [1] */
    }};
}
Run Code Online (Sandbox Code Playgroud)

除了[1]处的行导致空指针异常外,所有看起来都很好.据推测,这意味着子类中的静态初始化程序在父类的运行之前运行.这让我感到惊讶,因为我认为它会先在任何新的导入中运行静态块,然后再在instatiated子类中运行.

我在这个假设中是对的吗?有没有办法控制或解决这种行为?

更新:

事情甚至更奇怪.我尝试了这个(注意'new ParentClass()'行):

class ParentClass
{
    public ParentClass()
    {
        System.out.println(THE_SET);
    }

    protected final static Set THE_SET = new Set() {{
        add("one");
        add("two");
        add("three");
    }};
}


class SubClass extends ParentClass
{
    protected final static Set THE_SET = new …
Run Code Online (Sandbox Code Playgroud)

java inheritance static initialization static-initializer

5
推荐指数
1
解决办法
1841
查看次数

Java - 静态初始化块内部的类类型

是否可以从静态初始化块内部获取类类型?

这是我目前拥有的简化版本::

class Person extends SuperClass {

   String firstName;

   static{
      // This function is on the "SuperClass":
      //  I'd for this function to be able to get "Person.class" without me
      //  having to explicitly type it in but "this.class" does not work in 
      //  a static context.
      doSomeReflectionStuff(Person.class);     // IN "SuperClass"
   }
}
Run Code Online (Sandbox Code Playgroud)

这更接近我正在做的事情,即初始化一个保存有关对象及其注释等信息的数据结构......也许我使用了错误的模式?

public abstract SuperClass{
   static void doSomeReflectionStuff( Class<?> classType, List<FieldData> fieldDataList ){
      Field[] fields = classType.getDeclaredFields();
      for( Field field : fields ){
         // Initialize fieldDataList
      }
   } …
Run Code Online (Sandbox Code Playgroud)

java reflection static-initializer static-initialization

5
推荐指数
1
解决办法
3079
查看次数

什么{{ArrayList初始值设定器上的语法'确​​实如此

我最近发现在我看来是静态初始化ArrayList的新语法:
new ArrayList() {{ add("first"); add("second"); }};

我的问题是,那里到底发生了什么?这是定义静态块的快捷方式(我认为它需要static关键字)?或者只是一种定义默认构造函数的方法?别的什么?哪个版本的Java有效?

将非常感谢解释以及进一步阅读的链接.

编辑:我的测试类,用于显示初始化程序块是否在构造函数之前或之后执行.结果显示初始化程序块在其他构造函数代码之前执行:

import org.junit.Test;

public class InitializerBlockTest {
    class InitializerTest {
        {
        System.out.println("Running initalizer block");
        }

        public InitializerTest() {
            System.out.println("Running default constructor");
        }
    }

    class SubClass extends InitializerTest {
      {
        System.out.println("Running subclass Initializer block");
      }

      public SubClass()  {
        System.out.println("Running subclass constructor");
      }
    }

    @Test
    public void testIt() {
        new SubClass();
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

Running initalizer block
Running default constructor
Running subclass Initializer block
Running subclass constructor
Run Code Online (Sandbox Code Playgroud)

java arraylist static-initializer

5
推荐指数
1
解决办法
1195
查看次数