When I debug through Java code, I often see lot of properties of object that are useful to me in my application to get them and do something with them but I look at the API or javadocs, the class does not have any such properties or getter methods to get these property values. For example:
myPhoneCallObj.foo has value "bar" in debugger
myPhoneCallObj.baz has value otherObj which in turn has other values like otherObj.baz
I cannot do in Java:
String myValue = myPhoneCallObj.foo
as it would not compile in Java but in Groovy I can write above code and during runtime, it gets the value I need. How the same can be done in Java code?
myPhoneCallObj is an instance of Java Interface PhoneCall and the debugger was showing this as of type PhoneCallImpl ( third party implementation of the interface). I do not have access to source code of that third party to look into to understand but the Interface has complete documentation and Javadoc for the APIs.
Given a class like:
class X
{
private int value;
#Override
public String toString()
{
return (Integer.toString(value));
}
}
You can do this:
import java.lang.reflect.Field;
public class Test
{
public static void main(final String[] argv)
throws NoSuchFieldException,
IllegalArgumentException,
IllegalAccessException
{
final X x;
x = new X();
System.out.println(x);
changeValue(x);
System.out.println(x);
}
private static void changeValue(final X x)
throws NoSuchFieldException,
IllegalArgumentException,
IllegalAccessException
{
final Class<X> clazz;
final Field field;
clazz = X.class;
field = clazz.getDeclaredField("value");
field.setAccessible(true);
field.set(x, Integer.MAX_VALUE);
}
}
The key here is the call to field.setAccessible(true); which says that even though value is private allow it to be accessed.
However there is typically a reason why a field is private, and you should not be surprised if your code breaks with a later release of the 3rd party code that you are manipulating.
Are these properties private or protected in scope? The only properties that you will be able to directly access are public properties, but all variables will show up in a debug object inspector.
If you absolutely need to get the value, you can use reflection. (Which is likely what Groovy is doing)
Related
I have an activity with some final variables. I extracted their values (let's assume they're all Strings) into a resources file.
The problem:
If I directly assign them on the instantiation (as following):
private final String PREFERENCE_NAME = getResources().getString(R.string.preference_name);
I get the following error:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference
I understand the problem; the onCreate() method has not been called yet which means I cannot access context-related methods (getResources()).
If I want to assign the value in the onCreate() method of the activity, I get the error Cannot assign value to final variable 'PREFERENCE_NAME'
The question is: How can I get my final variables to be assigned from the resources file? And if this is not possible, what is the best practice for a solution?
Thanks in advance.
The simple answer is that you can't.
Variables declared final can only be set when the object is instantiated (i.e. in the constructor or with initialiser code).
Either use getResources().getString(R.string.preference_name); all the time or use a non-final variable.
The complex answer is that you can but that you shouldn't.
When you declare a variable final the compiler and VM uses this to make optimisations and assumptions. It can do this because the variable is guaranteed to never change. Changing it after it has been initialised can cause really weird bugs so you absolutely should not do that.
Here's how you do it:
public class FinalMessage {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
FinalMessage f = new FinalMessage("Hello World!");
System.out.println(f.getMessage());
f.changeFinalMessage("Hello Mars!");
System.out.println(f.getMessage());
}
private final String message;
public FinalMessage(String message) {
this.message = message;
}
void changeFinalMessage(String newMessage) throws IllegalAccessException, NoSuchFieldException {
final Field field = FinalMessage.class.getDeclaredField("message");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(this, newMessage);
}
String getMessage() {
return message;
}
}
This will output:
Hello World!
Hello Mars!
Great, so we changed a final variable. No problem right?
Well, take this example instead:
public class FinalMessage {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
FinalMessage f = new FinalMessage();
System.out.println(f.getMessage());
f.changeFinalMessage("Hello Mars!");
System.out.println(f.getMessage());
}
private final String message = "Hello World!";
void changeFinalMessage(String newMessage) throws IllegalAccessException, NoSuchFieldException {
final Field field = FinalMessage.class.getDeclaredField("message");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(this, newMessage);
}
String getMessage() {
return message;
}
}
This will output:
Hello World!
Hello World!
Wait, what?
The problem is that the compiler can see that the variable message is always going to be "Hello World!" so it inlines "Hello World!" instead of our call to f.getMessage(). If you run this in a debugger you will see the debugger reflect the updated message in the instance to "Hello Mars!" but since the variable is actually never accessed it won't affect the outcome of the program.
So to summarize: You can update final fields via reflection (granted that there is no Security Manager present that prevents you from doing it), but you should not do it since it can have very, very weird side-effects.
I am not responsible if your house gets termites or your cat catches on fire if you actually decide to implement this.
In this case I think the best thing to do it just make multiple calls to the resources. You still only have to change the value in one place and the call to getResources() isn't an expensive one.
Use your application context:
Create an application class:
public class MyApplication extends Application {
private static Context mContext;
#Override
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
}
public static String getStr(int resId) {
return mContext.getString(resId);
}
}
Use it in your manifest:
<application
android:name=".MyApplication"
...
Call it anywhere in your application:
static final String NAME = MyApplication.getStr(R.string.app_name);
You can use a factory pattern to solve this issue.
The builder is a class that aggregates the data needed to create your object, and when you are done - you just build your class.
In this approach, the data needed to generate the object is also available to the factory, and he can easily create the object, and initialize the final field when invoking its constructor.
You will have something like
class MyFactory {
private Resource getResources() { ... }
public MyObject build() {
String perference_name = getResources().getString(R.string.preference_name);
/...
return new MyObject(perfence_name ,....);
}
}
You can simply declare it as a final method:
private final String PREFERENCE_NAME() {
return getResources().getString(R.string.preference_name);}
I'm trying to write an expression or series of statements of Java source code that when written inside a static method evaluates to null, but if the method is non-static evaluates to this.
My initial idea was to 'overload' on static vs non-static, as below:
public class test {
public void method1() {
System.out.println(getThisOrNull());
}
public static void method2() {
System.out.println(getThisOrNull());
}
private static Object getThisOrNull() {
return null;
}
private Object getThisOrNull() {
return this;
}
public static void main(String[] args) {
test t = new test();
System.out.println(t);
t.method1();
t.method2();
}
}
Unfortunately this isn't actually legal Java, you can't 'overload' like that and it just gives a compiler error:
test.java:14: error: method getThisOrNull() is already defined in class test
private Object getThisOrNull() {
^
1 error
Clearly in an ideal world I wouldn't write it like that to begin with, but the problem is this code will be generated automatically by a tool that is not really semantically or syntactically enough to distinguish between the static vs non-static case.
So, how can I write some source code that, although byte for byte identical compiles and behaves differently in depending on the presence of the static modifier for the method?
This can be achieved with a trick and a bit of help from Java's reflection facilities. It's ugly, but it works:
import java.lang.reflect.Field;
public class test {
public void method1() {
System.out.println(getThisOrNull(new Object(){}));
}
public static void method2() {
System.out.println(getThisOrNull(new Object(){}));
}
private static Object getThisOrNull(final Object o) {
for (Field f: o.getClass().getDeclaredFields()) {
if (f.getType().equals(test.class)) {
try {
return f.get(o);
}
catch (IllegalAccessException e) {
// Omm nom nom...
}
}
}
return null;
}
public static void main(String[] args) {
test t = new test();
System.out.println(t);
t.method1();
t.method2();
}
}
This compiles and runs as hoped for:
test#183f74d
test#183f74d
null
The trick that makes this possible is the use of new Object(){}, which creates a new, anonymous class within the existing method that we're trying to figure out if it's static or not. The behaviour of this is subtly different between the two cases.
If the goal were just to figure out if the method is static or not we could write:
java.lang.reflect.Modifiers.isStatic(new Object(){}.getClass().getEnclosingMethod().getModifiers())
Since we want to get this (when available) we need to do something slightly different. Fortunately for us classes defined within the context of an instance of an object in Java get an implicit reference to the class that contains them. (Normally you'd access it with test.this syntax). We needed a way to access test.this if it existed, except we can't actually write test.this anywhere because it too would be syntactically invalid in the static case. It does however exist within the object, as a private member variable. This means that we can find it with reflection, which is what the getThisOrNull static method does with the local anonymous type.
The downside is that we create an anonymous class in every method we use this trick and it probably adds overheads, but if you're backed into a corner and looking for a way of doing this it does at least work.
I have main class with a private static method. I want to access this method from another java class. I tried some ways,however they didnt work. How can I access the method?
below main class like this;
public class RandomGenerate {
public static void main(String[] args) throws Exception {
System.out.print.ln("main method");
}
private static synchronized void createRandom(PersonObj person, int number, List s) {
System.out.println("deneme");
}
}
And I want to call createRandom from another java class like this;
public class Deneme {
RandomGenerate rg = new RandomGenerate();
RandomGenerate.createRandom(person, number, sList);
}
Then, netbeans shows method has private access.
You shouldn't access a private function/variable from outside of that class. If you need to access a private variable of a class, you can create an accompanying getter for that variable, and call the getter function on the class.
For functions, if the class you are trying to access the function from is in the same package, or is a subclass as the class with the function, change private to protected. protected allows members in the same package, or subclasses, to access the item, but nothing outside of the package.
A good read on visibility in Java is: http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
That shows a table:
Access Levels
Modifier Class Package Subclass World
public Y Y Y Y
protected Y Y Y N
no modifier Y Y N N
private Y N N N
Primarily
If you need to use it outside the class, make it public (or protected if you need it only in subclasses, or the default [no keyword at all] if you need it just in the package). If you need to use it outside the class and it's private and you can't make it not private, that's a design problem you should fix.
But...
...you can work around it using reflection (tutorial, docs), which allows you to get the method and call it even though it's private. Once you have the Method object, you have to call setAccessible to true before you call it.
But again, that's a workaround. Use the correct access modifier.
private methods are not accessible from another class by definition. If you need to call it you can create another public method that internally calls the private one or change the access modifier to public/protected/default.Example:
private static String secretMethod() { return "secret"; }
public static String knownMethod() { return secretMethod(); }
You will want to choose the proper access modifier for the method, the options are: public, protected, default (which is indicated by not providing a modifier), and private.
A good explanation is here: http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
As mentioned in the comments, you can use public to open it up, but if you don't want such a wide access, you could start with default (which allows you to access the method if you're in the same package), or protected (which is the same as default, but also allows child classes to access the method, if you wanted to extend the class).
As a general rule, stick with the most restrictive permission. It's easier to open up permissions later, but very hard to remove them.
You can not access Private methods outside the class which defines this method. You should make it Public to give full access to any classes or protected to give access to all the classes in the same package.
Click [here] http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html For more reference.
If you really wish to access private method, you will have to use Java Reflection. See this sample code.
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Workspace {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
ClassWithPrivateMethod cwpm = new ClassWithPrivateMethod();
Method m = cwpm.getClass().getDeclaredMethod("privateMethod", String.class);
m.setAccessible(true); //This is a key statement for accessing private methods
m.invoke(cwpm, "test");
}
}
class ClassWithPrivateMethod {
private void privateMethod(String someParam){
System.out.println("I am private!!!");
System.out.println("Parameter: " + someParam);
}
}
This code will print following output:
I am private!!!
Parameter: test
Just change the visibility from private to public so other Instances can access them. Private means it is only for the own class available.
In Java, static methods and variables can be accessed through object reference, like in the program below, which is working absolutely fine:
//StaticDemo.java
class StaticVerifier{
private int a,b;
public StaticVerifier(int a,int b){
this.a = a;
this.b = b;
System.out.println("Values are "+this.a+" "+this.b);
}
public static void takeAway(){
System.out.println("This is a static method...");
}
}
public class StaticDemo{
public static void main(String[] args){
StaticVerifier sv = new StaticVerifier(3,4);
sv.takeAway();
}
}
But when I tried the same code converted in C# its not allowing the object to access the static method and giving compile time error. See the code and associated error below:
//StaticDemo.cs
using System;
public class StaticVerifier{
private int a,b;
public StaticVerifier(int a,int b){
this.a = a;
this.b = b;
Console.WriteLine("Values are "+this.a+" "+this.b);
}
public static void takeAway(){
Console.WriteLine("This is a static method...");
}
}
public class StaticDemo{
public static void Main(string[] args){
StaticVerifier sv = new StaticVerifier(3,4);
sv.takeAway(); // here, unable to access static methods, but can use classname rather than objectname !
}
}
Errors:
StaticDemo.cs(17,3): error CS0176: Member 'StaticVerifier.takeAway()' cannot be
accessed with an instance reference; qualify it with a type name instead
StaticDemo.cs(10,21): (Location of symbol related to previous error)
Can anybody tell me why C# don't have this accessibility and Java has, though both are based on object oriented paradigm?(I mostly mean "why the vendors had made it so?")
Accessing static members through an instance reference is a quirk of Java's, nothing related to object orientation.
The correct way (both in C# and Java) is to access takeAway via the class reference, StaticVerifier.takeAway(). Java allows you to use an instance reference, but again, that's a quirk, and I believe it's just about only Java that has that quirk.
This quirk of Java's can be very confusing. For instance:
public class Example {
public static final void main(String[] args) {
Example e = null;
e.staticMethod();
}
static void staticMethod() {
System.out.println("staticMethod");
}
}
One might expect that to fail with a NullPointerException. But it doesn't, because staticMethod is static, so you don't need an instance to call it, so the fact that e is null is irrelevant.
Accessing the static through an instance reference also results in unnecessary bytecode being generated. e.staticMethod(); results in:
2: aload_1
3: pop
4: invokestatic #2 // Method staticMethod:()V
e.g., the contents of e are loaded and then popped. But Example.staticMethod(); just generates
2: invokestatic #2 // Method staticMethod:()V
Not that it really matters, the optimizer in the JVM will probably fix it, but...
In Java the call
sv.takeAway();
is actually compiled to
StaticVerifier.takeAway()
You can check it by calling javap -c StaticVerifier.class.
A good IDE will warn you if you call a static method on instance. So C# is just more strict in this.
Because in Java sv.takeAway() actually mean StaticVerifier.takeAway() an this little confusing when you access static method via object reference (it is fun that sv can be null and all will work just fine).
In C# they decide to not include such confusion in language and have only one way to access statics e.g. StaticVerifier.takeAway()
How can I programmatically enable assert for particular classes, instead of specifying command line param "-ea"?
public class TestAssert {
private static final int foo[] = new int[]{4,5,67};
public static void main(String []args) {
assert foo.length == 10;
}
}
Try
ClassLoader loader = getClass().getClassLoader();
setDefaultAssertionStatus(true);
or
ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true);
EDIT:
based on the comments
ClassLoader loader = ClassLoader.getSystemClassLoader();
loader.setDefaultAssertionStatus(true);
Class<?> c = loader.loadClass("MyClass");
MyClass myObj = (MyClass) c.newInstance();
public class MyClass {
private static final int foo[] = new int[]{4,5,67};
MyClass()
{
assert foo.length == 10;
}
}
This was a comment to #bala's good answer, but it got too long.
If you just enable assertions then call your main class--your main class will be loaded before assertions are enabled so you will probably need a loader that doesn't reference anything else in your code directly. It can set the assertions on then load the rest of the code via reflection.
If assertions aren't enabled when the class is loaded then they should be "Compiled Out" immediately so you are not going to be able to toggle them on and off. If you want to toggle them then you don't want assertions at all.
Due to runtime compiling, something like this:
public myAssertNotNull(Object o) {
if(checkArguments)
if(o == null)
throw new IllegalArgumentException("Assertion Failed");
}
Should work nearly as fast as assertions because if the code is executed a lot and checkArguments is false and doesn't change then the entire method call could be compiled out at runtime which will have the same basic effect as an assertion (This performance depends on the VM).
You can enable/disable assertions programmatically too:
http://download.oracle.com/docs/cd/E19683-01/806-7930/assert-5/index.html
It is possible to enable or disable assertions using reflection. As usual with reflection, the solution is fragile and may not be appropriate for all usage scenarios. However, if applicable and acceptable, it is more flexible than setClassAssertionStatus because it allows to enable/disable assertions checks at various points in the execution, even after the class is initialized.
This technique requires a compiler that generates a synthetic static field to indicate whether assertions are enabled or not. For example, both javac and the Eclipse compiler generate field $assertionsDisabled for any class that contains an assert statement.
This can be verified as follows:
public class A {
public static void main(String[] args) {
assert false;
System.out.println(Arrays.toString(A.class.getDeclaredFields()));
}
}
Setting the desired assertion status just comes down to setting this field (note the inverted boolean value):
// Helper method in any class
public static void setAssertionsEnabled(Class<?> clazz, boolean value)
throws ReflectiveOperationException
{
Field field = clazz.getDeclaredField("$assertionsDisabled");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(Test.class, !value);
}
The simplest & best way can be:
public static void assertion(boolean condition, String conditionFailureMessage)
{
if(!condition)
throw new AssertionError(conditionFailureMessage);
}
No need to set -ea as VM argument .
call the function like :
assertion(sum>=n,"sum cannot be less than n");
If assertion fails, code will give AssertionError, else code will run safely.