The following code is part of a larger application:
public static void METHOD_NAME(Object setName, int setLength){
tryLoop:
for( ; ; ){
try{
setName = new Stack(setLength);
break tryLoop;
}catch (InstantiationException e){
System.err.println(e.getMessage());
SET_NUM(1);
continue tryLoop;
}
}
}
Whenever I try to use the stack object that was initialized within the try block, it cannot be found unless the reference to it is within the try block. Why is this and how can I avoid it in the future?
I suspect you're under the impression that this:
setName = new Stack(setLength);
will have some impact on the argument passed in by the caller. It won't. Java is strictly pass-by-value, whether that value is a primitive type value or a reference.
In other words, if you do this:
Object foo = null;
METHOD_NAME(foo, 5);
then foo will still be null afterwards.
I suggest you return the value from your method instead. For example:
public static Stack METHOD_NAME(Object setName, int setLength){
while(true) {
try {
return new Stack(setLength);
} catch (InstantiationException e){
System.err.println(e.getMessage());
SET_NUM(1);
}
}
}
Note the return instead of breaking to a label, and while(true) which I find more readable than for (; ;).
Well, that method is ... pretty unorthodox Java code, to say at least.
Additionally it doesn't seem to have any meaningful result whatsoever. It sets its own parameter to a new value (entirely ignoring the original one) and never returns anything or modifies any object that it gets passed.
So unless the construction of a Stack object has some effect that is visible from the outside, this methods doesn't do anything useful (in the "no-exception" case).
Declare a method scode variable before your try block and assign setName to it. Then assign new Stack() to that variable in your try block and return it at the end of your method.
Modifying the value of a parameter is usually bad practice anyways.
No idea what you're using a label for -- continue; will work fine. Other things are a bit suspect here too. The scope for a variable declared inside a try block is just the try block. Setting 'setName' will do nothing as Java passes an object, and changing the reference to point to a new object will not affect the passed object. As for not being able to use setName in the current bit of code, you can avoid it by taking it outside of the block, or doing everything you need to inside the try block :) You can also return it to allow the caller to use it. Why are you trying to catch InstantiationException? You'd be better off checking that setLength is a valid size and let uncaught exceptions validate the integrity of Java itself.
Java does not support pass-by-reference, so the assignment to setName does not pass any value back to the caller.
The obvious rewrite of your code is as follows:
public static Object METHOD_NAME(int setLength) {
while (true) {
try {
return new Stack(setLength);
} catch (InstantiationException e){
System.err.println(e.getMessage());
SET_NUM(1);
}
}
}
Related
Variable used in lambda expression should be final or effectively final
When I try to use calTz it is showing this error.
private TimeZone extractCalendarTimeZoneComponent(Calendar cal, TimeZone calTz) {
try {
cal.getComponents().getComponents("VTIMEZONE").forEach(component -> {
VTimeZone v = (VTimeZone) component;
v.getTimeZoneId();
if (calTz == null) {
calTz = TimeZone.getTimeZone(v.getTimeZoneId().getValue());
}
});
} catch (Exception e) {
log.warn("Unable to determine ical timezone", e);
}
return null;
}
Although other answers prove the requirement, they don't explain why the requirement exists.
The JLS mentions why in §15.27.2:
The restriction to effectively final variables prohibits access to dynamically-changing local variables, whose capture would likely introduce concurrency problems.
To lower risk of bugs, they decided to ensure captured variables are never mutated.
This also applies for anonymous inner classes
A final variable means that it can be instantiated only one time.
in Java you can't reassign non-final local variables in lambda as well as in anonymous inner classes.
You can refactor your code with the old for-each loop:
private TimeZone extractCalendarTimeZoneComponent(Calendar cal,TimeZone calTz) {
try {
for(Component component : cal.getComponents().getComponents("VTIMEZONE")) {
VTimeZone v = (VTimeZone) component;
v.getTimeZoneId();
if(calTz==null) {
calTz = TimeZone.getTimeZone(v.getTimeZoneId().getValue());
}
}
} catch (Exception e) {
log.warn("Unable to determine ical timezone", e);
}
return null;
}
Even if I don't get the sense of some pieces of this code:
you call a v.getTimeZoneId(); without using its return value
with the assignment calTz = TimeZone.getTimeZone(v.getTimeZoneId().getValue()); you don't modify the originally passed calTz and you don't use it in this method
You always return null, why don't you set void as return type?
Hope also these tips helps you to improve.
From a lambda, you can't get a reference to anything that isn't final. You need to declare a final wrapper from outside the lamda to hold your variable.
I've added the final 'reference' object as this wrapper.
private TimeZone extractCalendarTimeZoneComponent(Calendar cal,TimeZone calTz) {
final AtomicReference<TimeZone> reference = new AtomicReference<>();
try {
cal.getComponents().getComponents("VTIMEZONE").forEach(component->{
VTimeZone v = (VTimeZone) component;
v.getTimeZoneId();
if(reference.get()==null) {
reference.set(TimeZone.getTimeZone(v.getTimeZoneId().getValue()));
}
});
} catch (Exception e) {
//log.warn("Unable to determine ical timezone", e);
}
return reference.get();
}
Java 8 has a new concept called “Effectively final” variable. It means that a non-final local variable whose value never changes after initialization is called “Effectively Final”.
This concept was introduced because prior to Java 8, we could not use a non-final local variable in an anonymous class. If you wanna have access to a local variable in anonymous class, you have to make it final.
When lambda was introduced, this restriction was eased. Hence to the need to make local variable final if it’s not changed once it is initialized as lambda in itself is nothing but an anonymous class.
Java 8 realized the pain of declaring local variable final every time a developer used lambda, introduced this concept, and made it unnecessary to make local variables final. So if you see the rule for anonymous classes has not changed, it’s just you don’t have to write the final keyword every time when using lambdas.
I found a good explanation here
In your example, you can replace the forEach with lamdba with a simple for loop and modify any variable freely. Or, probably, refactor your code so that you don't need to modify any variables. However, I'll explain for completeness what does the error mean and how to work around it.
Java 8 Language Specification, §15.27.2:
Any local variable, formal parameter, or exception parameter used but not declared in a lambda expression must either be declared final or be effectively final (§4.12.4), or a compile-time error occurs where the use is attempted.
Basically you cannot modify a local variable (calTz in this case) from within a lambda (or a local/anonymous class). To achieve that in Java, you have to use a mutable object and modify it (via a final variable) from the lambda. One example of a mutable object here would be an array of one element:
private TimeZone extractCalendarTimeZoneComponent(Calendar cal, TimeZone calTz) {
TimeZone[] result = { null };
try {
cal.getComponents().getComponents("VTIMEZONE").forEach(component -> {
...
result[0] = ...;
...
}
} catch (Exception e) {
log.warn("Unable to determine ical timezone", e);
}
return result[0];
}
A variable used in lambda expression should be a final or effectively final, but you can assign a value to a final one element array.
private TimeZone extractCalendarTimeZoneComponent(Calendar cal, TimeZone calTz) {
try {
TimeZone calTzLocal[] = new TimeZone[1];
calTzLocal[0] = calTz;
cal.getComponents().get("VTIMEZONE").forEach(component -> {
TimeZone v = component;
v.getTimeZoneId();
if (calTzLocal[0] == null) {
calTzLocal[0] = TimeZone.getTimeZone(v.getTimeZoneId().getValue());
}
});
} catch (Exception e) {
log.warn("Unable to determine ical timezone", e);
}
return null;
}
to answer to > Variable used in lambda expression should be final or effectively final JAVA
to workaround that in not an elegant way , 2 issues :
the side effect and the threading issue
final AtomicInteger e = new AtomicInteger(0);
new Thread(() -> {
e.addAndGet(1);
});
to be more precise, i agree is kind of the same but the idea behind using Lambda function is to avoid side affect, and when we are accessing this final reference in the lambda function to populate the value to get the result from outside, we are breaking this concept.
in the oldest post you might want to rewrite like that
cal.getComponents().getComponents("VTIMEZONE").streams().map(v->v.getTimeZoneId().getValue()).collect(Collectors.toList());
and for the threading aspect , we have the same issue with the side effect and additionally you will never know when to access to the Atomic variable to collect the result , you could put a CountDownLatch ... Better to work with CompletableFuture to handle the result and the synchronization aspect
if it is not necessary to modify the variable than a general workaround for this kind of problem would be to
extract the part of code which use lambda and use final keyword on method-parameter.
You can't re-assign the variable with new reference inside a lambda expression which is coming from outside scope of lambda.But you can certainly modify existing state of the object.So instead re-assigning 'calTz' to new reference.You can call setter methods on it to change its internal state.So this will work(if your VtimeZone is mutatble only):
calTz=new TimeZone();
cal.getComponents().getComponents("VTIMEZONE").forEach(component -> {
VTimeZone v = (VTimeZone) component;
v.getTimeZoneId();
calTz.setTimeZoneId("some value");
})
.But this is not a good practice.
Above code can also be replaced by.
if(calTz == null){
calTz=new TimeZone();
cal.getComponents().getComponents("VTIMEZONE").get(0).setTimeZoneId("some value");}
I want to reference an annotation value in one class from another class. Like here -
class A {
private static final String STATIC_STRING = B.class.getMethod("myMethod").getAnnotation(SomeAnnotation.class).name();
}
The problem here is that I cannot use this syntax because it requires getMethod to be wrapped in a try-catch which is not possible. Although I can use a static block to create this variable and just gulp the exception in catch block, I don't want to do that because if in future the method name is changed, compiler won't throw an error in the static block.
I was wondering if I could do something like
private static final String STATIC_STRING = (B::myMethod).getAnnotation(SomeAnnotation.class).name();
Note: neither B nor SomeAnnotation is my source, they come from another library.
I have 2 questions here
Is there a better way to get value from annotation, preferably without using any external library like Google Reflections or similar?
How can I use :: to get instance of java.lang.reflect.Method? Is it possible altogether? If yes, is vice-versa also possible, i.e. create supplier or mapper from Method's object?
For your first question, have you considered using a getter?
private static String getSomeAnnotationName() {
try {
return B.class.getMethod("myMethod").getAnnotation(SomeAnnotation.class).name();
} catch (NoSuchMethodException e) {
return null;
}
}
For your second question, I don't think getting a Method from :: is possible. This is because methods got from :: represent implementations of functional interfaces, not really methods. However, the reverse is possible. You can create a lambda like this:
Consumer<SomeType> consumer = x -> {
try {
yourMethod.invoke(someObject, x)
} catch (...) {
// again you have to ignore the exceptions here, unfortunately
}
};
I'll keep it brief, I have a Dog class like the following:
public class Dog
{
public void Foo()
{
System.out.println("Right Call");
}
public void Boo()
{
System.out.println("Wrong Call");
}
}
and a main method like following:
HashMap<String, Method> map = new HashMap<String, Method>();
Dog d = new Dog();
Method[] method = d.getClass().getMethods();
map.put("foo", method[0]);
Method a = map.get("foo");
try {
a.invoke(d, null);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
e.printStackTrace();
}
Whenever I run it again, it just arbitrarily gives Right Call or Wrong Call outputs.
I need to be sure that every time I place the "foo" key, It must to be calling the Foo() method, instead of Boo().
Apparently, It doesn't ease my "method call" problem. How can I overcome this issue? I must be calling the right method every time. I'm quite new to this reflections stuff, is there anything that I shouldn't be doing, or something that I'm doing wrong? Or is there a better way to implement this method calling?
EDIT: I've also tried LinkedHashMap, however, the result is the same.
Thank you.
From the javadoc of Class.getMethods():
The elements in the array returned are not sorted and are not in any particular order.
Yet, your code assumes that the element at index 0 is the method Foo(). Don't make this assumption. Find the method which has the name Foo.
That said, Reflection is probably not the right tool for the job you're trying to do. You should explain, at a higher level, what you're trying to do and why you think using reflection is a good idea. Usually, it's not.
This has nothing to do with putting the method in a map, as far as I can tell - you can remove the map part entirely and still face the same issue:
Dog d = new Dog();
Method methods = d.getClass().getMethods();
Method a = methods[0];
try {
a.invoke(d, null);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
e.printStackTrace();
}
Fundamentally, you're seeing the fact that getMethods() doesn't return the methods from a class in an order you should rely on. If you want to specifically call your Foo method (which should be foo to follow Java naming conventions), you should probably be using Class.getMethod("foo") to get the method by name.
Result of getMethods() is not sorted, so there is no guarantee that method[0] is Foo() (not Boo()). You need to check it before put to map as a value for "foo" key.
You could off course also use the following reflection:
Dog d = new Dog();
map.put("foo", d.getClass().getMethod("Foo");
Method m = map.get("foo");
m.invoke()
This code is obviously missing all the try catch and some other stuff, but it does show you the important bit. You should never rely on the order in the getMethods(). Instead, if you know what the method is called, always use the getMethod call to get it by name. This way, you're sure to get the correct method.
I think the Map has caused a bit of a red herring.
Dog d = new Dog();
try {
d.getClass.getMethod("Foo").invoke(d, null);
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
Not one hundred percent sure on this, but I believe that you will also need to catch NoSuchMethodException.
I will say, unless you are just trying to learn about the reflection api, I would think twice before using reflection. In most cases, it is not the right tool for the job.
Suppose we have a case where a variable is declared in certain conditions:
if (x = 1)
boolean z = true;
Later on, we'd like to test if the variable z exists with try-catch. Is this possible and if so, what exception should we catch?
try {
if (z)
//do smth
} catch (<exception?> ex) {
//do smth_else
}
Of course it would be possible to declare z before and change it's value accordingly in if block, but just hypothetically, is the above possible in Java?
Python for example has NameError that will be raised when accessed local or global variable is not declared.
Thanks!
HSI.
What if you declared your variable like this:
Boolean x = null;
In that case you could check for it being null or not.
An even better alternative would be using an enum to represent the uninitialized value:
public enum MyEnum {
UNINITIALIZED, TRUE, FALSE;
}
because if you will try to maintain your code several months later you (or someone else) may be puzzled about the Boolean being null.
we'll get compilation error if the variable we are using is not declared or is not visible in current scope.
If it is declared we can check for NullPointerException if that was object. In case of primitive data types we should check for default values.
Suppose we have a case where a variable is declared in certain conditions:
Well it is difficult to assume because that would not compile:
you should use == to test for equality
you can't declare a variable in an if statement unless there is a block
Now assuming you enclose that declaration inside a block, the scope of that variable would be that block and you wouldn't be able to use it in your try / catch block (unless it is inside the if block of course, but I don't think that's what you want).
No, this is not possible in Java. You have to have the variable declared before you can refer to it, otherwise you will get a compilation error.
Boolean z = null;
if (x = 1){
z = true;
}
if(z == null){
//not initialized
}else{
//initialized
}
it's not possible, Java is a strongly typed programming language because every variable must be declared with a data type before it can be used.
int x = 1;
boolean z = null;
if (x == 1)
z = true;
try {
if (z)
//do smth
} catch (NullPointerException npe ) {
//do smth_else
}
So far I understand , you wont be able to compile this piece of code. I can not remember any exception class but what I think is even if you "Invent" exception for this type of error. It won't compile. Because default values of primitive types are assigned to uninitialized class variables called fields but for variable used in method body, it gives compile time error
Is it possible to get a Object that is instanced in the Code by a String at Runtime?
Somthing like that:
public String xyz = "aaaa_bbb";
getObject("xyz").some function of String (e.g.: .split("_"))
Thanks
Here's an example
If it's a class field, you can get it by name like this.
import java.lang.reflect.Method;
public class Test {
public String stringInstance = "first;second";
public void Foo() {
try {
Object instance = getClass().getDeclaredField("stringInstance").get(this);
Method m = instance.getClass().getMethod("split", String.class);
Object returnValue = m.invoke(instance, ";");
if(returnValue instanceof String[])
{
for(String s : (String[])returnValue )
{
System.out.println(s);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String a[]){
new Test().Foo();
}
}
If it's a local method variable you are trying to invoke on, then you might be able to get at to the variable in from the current method from the call stack Thread.currentThread().getStackTrace() maybe.
It is hard to make out what you are asking, but you can fetch field values by name using reflection. Something like this:
Class c = this.getClass(); // or Someclass.class
Field f = c.getDeclaredField("xyz");
String value = (String) f.get(this);
... = value.split("_");
(I've left out a lot of exception handling ...)
But as a comment points out, if you are really trying to implement an associative array, there are better ways of doing this in Java; e.g. using a Map class.
You might have to rephrase the question.
If you just want to get the "aaaa" and "bbb" strings from the initial string, you can use StringTokenizer
If your String is a member field of your object, you can go take a look at the Field class.
However, I have to warn you that the code that you'll end up with will be by far longer than what you expect here. Indeed, you'll have to do some operations :
Get the Field obejct associated to xyz
Get method from its name and parameters list (using as an example Class#getDeclaredMethod(...))
Invoke the method on this particular instance
Each of these steps will eb a rather obscure line of code, with a bunch of throwed exceptions.
So, if you have an alternative, well, use it !
I have custom components on a jPanel and i would like to work with them without repainting them. I knwo if i use a List or Map that it is possible but i have to change the value in the Map and then repaint the GUI with the infomration in the Map.