3

I have a class:

public class TextViewAttachedProperties {
    public static final String NAMESPACE = "http://schemas.android.com/apk/lib/com.zworks.mvvmandroid";

    private static final Handler uiHandler = new Handler(Looper.getMainLooper());

    private static final String DATA_CONTEXT = "DataContext";
    private static final String TEXT = "Text";

    private static final Listener<PropertyChangedEventArgs<String>> textChanged = new Listener<PropertyChangedEventArgs<String>>() {

        @Override
        public void onEvent(final PropertyChangedEventArgs<String> args) {
            final TextView element = (TextView) args.getSource();

            if (element != null && args.getNewValue() != null)
                uiHandler.post(new Runnable() {

                    @Override
                    public void run() {
                        element.setText(args.getNewValue());
                    }
                });
        }
    };

    // This two statements have side effects I'm counting on to execute
    private static final AttachedProperty<Object> dataContext = AttachedProperty
        .newProperty(DATA_CONTEXT, NAMESPACE, TextView.class, null); 
    private static final AttachedProperty<String> text = AttachedProperty
        .newProperty(TEXT, NAMESPACE, TextView.class, "", textChanged);
}

And the problem is it is only run if I instantiate that class.

How can I force it to be run no matter what?

zduny
  • 2,481
  • 1
  • 27
  • 49
  • It is somewhat irritating. I have a similar issue myself and I just give each class a static .init() method and make it explicit. It feels dirty but it does work. I don't think there is a clean way to do this because the JVM doesn't even know the class exists until you try to use it – Richard Tingle Apr 25 '14 at 19:52
  • There should be something like "static" marker that would tell JVM to load class just when it is in the .jar and not to wait for it's name to be mentioned... – zduny Apr 25 '14 at 19:58
  • that would be lovely! But as I say, it doesn't know the class exists yet, so it can't look for a marker. You could go through every single class in the jar and manually load it but that wouldn't be too kind on performance – Richard Tingle Apr 25 '14 at 19:59

2 Answers2

3

Use

Class.forName("TextViewAttachedProperties");

The javadoc states

Returns the Class object associated with the class or interface with the given string name. Invoking this method is equivalent to:

Class.forName(className, true, currentLoader)

where currentLoader denotes the defining class loader of the current class.

where true specifies

initialize - whether the class must be initialized

When the class is initialized, the static initializers will be executed and static fields will be initialized.

There are other ways to initialize a type such as accessing a static non-constant variable of the type, invoking a static method of the class, or instantiating the class. They are all described in the Java Language Specification. More or less.

Community
  • 1
  • 1
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
1

Static initialization blocks run when the JVM first sees a mention of the class. That is, when the class gets loaded.

You don't need to create an instance, but you do need to mention/reference the class in some way. There are a number of ways you can do this that will do the trick.

FrobberOfBits
  • 17,634
  • 4
  • 52
  • 86
  • So if I'm writing a library I have to mention that class in some method (constructor) that user has to call to use that library, right? – zduny Apr 25 '14 at 19:53
  • Read the link I provided. My understanding is that the first time the class is mentioned anywhere, it forces the JVM to load the class. When that happens, the static block fires. There are many ways to force loading the class; the second answer in this thread is an equally good way to do it. Yet another way to do it would be to add mention of this class to the static block of something you're sure will get created. – FrobberOfBits Apr 25 '14 at 19:55