Can a package final variable be changed through reflection?
Say I have this:
public class Widget {
final int val = 23;
}
Can the val be changed through reflection if made accessible?
If so, is there any way to prevent it that without using the security manager?
YES. Try this code:
public static void main(String[] args) throws Exception {
Widget w = new Widget ();
Field m = Widget.class.getDeclaredField("val");
m.setAccessible(true);
m.set(w, 233);
System.out.println(m.get(w)); /// PRINT 233
}
Turns out, changing final members causes reflection-obtained values to differ from values returned by regular code! This is quite scary.
import java.lang.reflect.Field;
public class Test {
private static final class Widget {
private final int val = 23;
public int getVal() {
return val;
}
}
public static void main(String[] args) throws Exception {
Widget w = new Widget ();
Field m = Widget.class.getDeclaredField("val");
m.setAccessible(true);
m.set(w, 233);
Field m1 = Widget.class.getDeclaredField("val");
m1.setAccessible(true);
System.out.println(m.get(w)); /// PRINT 233
System.out.println(w.getVal()); /// PRINT 23
System.out.println(m1.get(w)); /// PRINT 233
}
}
Try this.
Widget() {
checkPerMission();
}
private void checkPerMission() {
Class self = sun.reflect.Reflection.getCallerClass(1);
Class caller = sun.reflect.Reflection.getCallerClass(3);
if (self != caller) {
throw new java.lang.IllegalAccessError();
}
}
Related
I have a class named PointOfSale which have a public method getTpid, but I failed when I want to call this method in my main class, I can only call "TPID_FIELD_NUMBER", how to solve this problem?
PointOfSale ps = new PointOfSale();
ps.TPID_FIELD_NUMBER; //correct
ps.getTpid();// error
public final class PointOfSale implements PointOfSaleOrBuilder {
public static final int TPID_FIELD_NUMBER = 1;
private int tpid_;
#java.lang.Override
public int getTpid() {
return tpid_;
}
}
public interface PointOfSaleOrBuilder {
int getTpid();
}
I think that you just need to add () at the end of your call.
ps.TPID_FIELD_NUMBER is a call for a constant.
If you want to call a method, you should call like this: ps.getTpid();
public static void main(String[] args) {
PointOfSale ps = new PointOfSale();
ps.getTpid();
}
The issue is with the line "ps.TPID_FIELD_NUMBER;". This will give "Not a statement" error. You should assign it to a variable for successful execution.
Your code should look like,
public static void main(String[] args) {
PointOfSale ps = new PointOfSale();
int num = ps.TPID_FIELD_NUMBER;
ps.getTpid();
}
How can I access private variable inside a class having private constructor.
And how can I change it's value if the variable is declared final from another
class.Have tried few links but not able to get as most of the solutions are having public constructor like:
Link i have tried
Code I have tried:
package com.test.app;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class Demo {
static Demo instance = null;
private int checkvalue = 10;
final private int checkvalue1 = 12;
private Demo() {
System.out.println("Inside Private Constructor");
System.out.println(checkvalue);
}
static public Demo getInstance() {
if (instance == null)
instance = new Demo();
return instance;
}
}
class Main {
public static void main(String args[]) {
try {
///this is showing me the value inside the constructor
Class clas = Class.forName("com.test.app.Demo");
Constructor<?> con = clas.getDeclaredConstructor();
con.setAccessible(true);
con.newInstance(null);
///how can i get the value of the private variables inside the class
Field f = Demo.class.getDeclaredField("checkvalue");
f.setAccessible(true);
////throwing me a error
//java.lang.IllegalArgumentException: Can not set int field com.test.app.Demo.checkvalue to java.lang.reflect.Constructor
System.out.println("" + f.get(con));
} catch (Exception e) {
e.printStackTrace();
}
}
}
if you would to change checkValue1 variable, you should to considere to not put this variable as final.
I created these two files in java and they don't compile. This error comes up:
cannot find symbol C02FootprintV1".
Why doesn't the program recognize the object? I am new to this.
How could I fix this problem?
public class CO2FootprintV1 {
private double myGallonsUsed;
private double myTonsCO2;
private double myPoundsCO2;
CO2FootprintV1(double gals) {
myGallonsUsed = gals;
}
public void calcTonsCO2() {
myTonsCO2 = myGallonsUsed * 0.878;
}
public double getTonsCO2() {
return myTonsCO2;
}
public void convertTonsToPoundsCO2() {
myPoundsCO2 = myTonsCO2 * 220462262;
}
public double getPoundsCO2() {
return myPoundsCO2;
}
}
public class CO2FootprintV1Tester {
public static void main(String[] args) {
double gals;
double tonsCO2, poundsCO2;
gals = 1300;
CO2FootprintV1 object = new C02FootprintV1(gals);
object.calcTonsCO2();
tonsCO2 = object.getTonsCO2();
object.convertTonsToPoundsCO2();
poundsCO2 = object.getPoundsCO2();
}
}
On the line
CO2FootprintV1 object = new C02FootprintV1(gals);
you have C02 (see zero two) on the right hand side, you meant for it to be
CO2FootprintV1 object = new CO2FootprintV1(gals);
or CO2 (see oh two). Also, you should consider that the error messages your tools give you might be correct.
Just change:
CO2FootprintV1 object = new C02FootprintV1(gals);
to:
CO2FootprintV1 object = new CO2FootprintV1(gals);
That's why it is important to have good naming practice.
You put a "0" (cero) instead of an "O" (letter):
CO2FootprintV1 object = new C02FootprintV1(gals);
Try this:
CO2FootprintV1 object = new CO2FootprintV1(gals);
I come from writing a lot of JavaScript, so bear with me.
I've got 3 HashMaps, which i reference in a method in a different class. My code (very simply) looks like so:
public class MainClass {
private HashMap<String,Nation> randomHashMap = new HashMap<String,Nation>();
DifferentClass d = new DifferentClass(this);
} //with getters/setters
public class DifferentClass {
private MainClass mc;
public void randomMethod() {
System.out.println("randomHashMap is " + (mc.getRandomHashMap() == null));
} //returns null
public DifferentClass(MainClass c) {
this.mc = c;
}
}
However, when I call them in my other method, they're null.
How do I create a new, empty HashMap?
You need to initialize your MainClass mc variable before using it in the DifferentClass#randomMethod method. Also, make sure you're using the mc variable instead of the MainClass.getRandomHashMap() method (by your actual code, we don't know how it behaves). Your code will look like this:
public class DifferentClass {
private MainClass mc = new MainClass();
public void randomMethod() {
//assuming getRandomHashMap is the getter of randomHashMap attribute (and non static)
System.out.println("randomHashMap is " + (mc.getRandomHashMap() == null));
}
}
public class MainClass {
private HashMap<String,Nation> randomHashMap = new HashMap<String,Nation>();
DifferentClass d = new DifferentClass(this);
public HashMap<String,Nation> getRandomHashMap() {
return this.randomHashMap;
}
} //with getters/setters
The code you posted is in fact perfectly all right as far as field initialization. I made an SSCCE from it with minimal intervention:
class Nation{}
public class MainClass {
private HashMap<String,Nation> randomHashMap = new HashMap<String,Nation>();
DifferentClass d = new DifferentClass(this);
public Object getRandomHashMap() {
return randomHashMap;
}
public static void main(String[] args) {
new MainClass().d.randomMethod();
}
} //with getters/setters
class DifferentClass {
private MainClass mc;
public void randomMethod() {
System.out.println("randomHashMap is " + (mc.getRandomHashMap() == null));
} //returns null
public DifferentClass(MainClass c) {
this.mc = c;
}
}
and it prints
randomHashMap is false
which proves that randomHashMap is indeed non-null.
What I want to do is access a variable stored in one class with a string.
For example I have
public class Values {
public static boolean enabled;
}
And then in a different part of the project I have the object and a string with the fields name. How do I get and set the value of the field?
If you have the name as a string, you should use reflection:
import java.lang.reflect.Field;
public class Values {
public static boolean enabled = false;
public static void main(String[] args) throws Exception {
Values v = new Values();
Field field = v.getClass().getField("enabled");
field.set( v, true );
System.out.println( field.get(v) );
}
}
Values.enabled = true;
or
Values.enabled = false;
Alternatively, you can create a static getter and setter for the Values class and call those static methods instead.
#Maricio Linhares's answer is very good; however, note that reflection is pretty slow. If you are doing this a lot you might have performance problems. An alternative might be to use a map. The code would follow as
public class Values {
public static Map<string,bool> variableMap;
public static void main(String[] args) throws Exception {
// adding a 'variable'
variableMap = new YourFavoriteMapImplementation();
variableMap.put("enabled",true);
// accessing the 'variables' value
bool val = variableMap.get("enabled");
System.out.println(val);
}
}