I want to set a key in java from the value that is set from a string
sorry i cant explain this to good so i wrote this in php and here
is a example.
class Test() {
public setField($key, $value) {
$this->{$key} = $value;
}
}
$class = new Test()
$class->setField("hello", "hello world");
echo $class->hello;
The map interface gives the requested behavior:
import java.util.HashMap;
public class StackOverflow {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<String, String>();
map.put("hello", "hello world");
System.out.println(map.get("hello"));
}
}
But you generally want to use variables as keys, and then you would need a method for setting and retrieving every variable.
public class Test {
private String hello;
public void setHello(String hello) {
this.hello = hello;
}
public String getHello() {
return hello;
}
}
public class StackOverflow {
public static void main(String[] args) {
Test test = new Test();
test.setHello("Hello world");
System.out.println(test.getHello());
}
}
Or you could make the variable public:
public class Test {
public String hello;
}
public class StackOverflow {
public static void main(String[] args) {
Test test = new Test();
test.hello = "Hello world";
System.out.println(test.hello);
}
}
Java does not have in-built dynamic variables like PHP. The simplest way to achieve the same functionality this is be to use a Map
public class Test {
private Map<String, String> map = new HashMap<String, String>();
public void setField(String key, String value) {
map.put(key, value);
}
public String getField(String key) {
return map.get(key);
}
}
and
Test test = new Test();
test.setField("hello", "hello world");
System.out.println(test.getField("hello"));
You'll have to do it manually in Java. Something along the lines of:
class Test(){
private HashMap<Object, Object> inner_objects;
public void setField(Object key, Object value) {
this.inner_objects.put(key, value);
}
public Object getField(Object key){
return this.inner_objects.get(key);
}
}
Of course this example could be improved in several ways, but it is just to give you the general idea.
But since there is no operator overloading, you can't make -> work as getField, so you will need to call getField(key) everytime.
Related
I have code like
public class Functionz {
public static boolean test() {
return true;
}
public static void main(String[] args) {
Function[] funcs = new Function[] {test}; // and others
for (Function func : funcs) {
func();
}
}
}
and my error is: cannot find symbol: test in the line with the function array declaration.
Hope this isn't a stupid question, very new to java, not new to object oriented languages like python and C++.
A Function in Java does takes one parameter as input and one as output.
You might declare parameter's type this way : Function<Integer, String> is a function that transforms an Integer into a String
Your method test() does not take any input value and outputs a boolean so it's a Supplier.
import java.util.function.Supplier;
public class Main {
public static boolean test() {
System.out.println("lorem ipsum");
return true;
}
public static void main(String[] args) {
Supplier[] funcs = new Supplier[] {Main::test}; // and others
for (Supplier func : funcs) {
func.get();
}
}
}
Your code would compile if test requires one (and only one parameter) like
import java.util.function.Function;
public class Main {
public static boolean test(String str) {
System.out.println(str);
return true;
}
public static void main(String[] args) {
Function[] funcs = new Function[] {(Object anyObject) -> test(anyObject.toString())}; // and others
for (Function func : funcs) {
func.apply("lorem ipsum");
}
}
}
Here's the list of those types
Please note that Function doesn't type its parameters in construction because you can't create arrays with generic type in Java (you might for specific usecases) => Use a List will help you here
import java.util.*;
class Pilot
{
protected String PILOT = "BSIT-1A";
public static void Subject()
{
String[] subs = {"Comprog11","WebDev","Digilog12","ComProg12"};
}
public static void Teacher()
{
String[] teach = {"Ms.a","Ms.b","Ms.c","Ms.d"};
}
}
class Pilot1 extends Pilot
{
protected String PILOT1 = "BSIT-1B";
public static void main(String[]args)
{
Pilot1 obj = new Pilot1();
System.out.println(obj.PILOT);
System.out.println(obj.PILOT1);
obj.Subject();
obj.Teacher();
}
how to display the values of Subject() and Teacher() if I put inside it a String?It doesnt have any compiler issues but when I ran it display only the
BSIT-1A
BSIT-1B
my expected output is
BSIT-1A
BSIT-1B
Comprog11
Webdev
Digilog12
Comprog12
Ms.a
Ms.b
Ms.c
Ms.d
You can return the array
public String[] subject() {
return {"Comprog11","WebDev","Digilog12","ComProg12"};
}
Then remove the inheritance. You don't need it for the main method. Make the pilot constants public or pass those strings into a class constructor and add a private field with a getter method, for example
Pilot a = new Pilot("BSIT-1A");
Pilot b = new Pilot("BSIT-1B");
System.out.println(a.getCode());
System.out.println(b.getCode());
Arrays.stream(a.subject()).forEach(System.out::println);
You need the either print the values in Subject() and Teacher() or make them return the values. Also calling static methods via objects is not a
good practice. They should be invoked by the class, like Pilot1.Subject().
class Pilot
{
protected String PILOT = "BSIT-1A";
public static void Subject()
{
String[] subs = {"Comprog11","WebDev","Digilog12","ComProg12"};
for(String sub : subs){
System.out.println(sub);
}
}
public static void Teacher()
{
String[] teach = {"Ms.a","Ms.b","Ms.c","Ms.d"};
for(String t : teach){
System.out.println(t);
}
}
}
I'm testing with Java reflection and trying to apply overloaded method to parameters according to their type..
However, I have NoSuchMethodException even though the method I tried to get is public. This exception still appears when I used getDeclaredMethod.
Here's the main program
public class Test {
public static void main(Object... inputs){
InputManipulation test = new InputManipulation();
for (Object input: inputs){
Class ownerClass = test.getClass();
Class inputClass = input.getClass();
Method method = ownerClass.getDeclaredMethod("add", inputClass);
method.invoke(test, "Testing reflection");
}
}
}
And here's the self-defined InputManipulation class
public class InputManipulation {
Integer total;
public InputManipulation(){this.total = 0;}
public void add(Integer num){this.total += num;}
public void add(String str){System.out.println(str);}
}
Thanks in advance!
I now changed the Test class as follows.. but the problem still exists.
public class Test {
public static void main(String[] args){
Test testExample = new Test();
testExample.testMethod("String1", 1, "String2");
}
public void testMethod(Object... inputs){
InputManipulation test = new InputManipulation();
for (Object input: inputs){
Class ownerClass = test.getClass();
Class inputClass = input.getClass();
Method method = ownerClass.getDeclaredMethod("add", inputClass);
method.invoke(test, "Testing reflection");
}
}
}
I also tried putting the inputClass into an array of Class, as suggested by another post, but it didn't help..
There seems to be a few issues with the initial code you provided and as others have suggested using an IDE would have pointed some of the issues out pretty quickly. However, I have taken your update and fixed the code to call the proper method in the loop you provided of input types.
First change your InputManipulation class like so:
public class InputManipulation {
Integer total;
public InputManipulation() {
this.total = 0;
}
public void add(Integer num) {
this.total += num;
System.out.println(this.total);
}
public void add(String str) {
System.out.println(str);
}
}
Now alter your Test class like so:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
public static void main(String[] args) {
Test testExample = new Test();
testExample.testMethod("String1", 1, "String2");
}
public void testMethod(Object... inputs){
InputManipulation test = new InputManipulation();
for (Object input: inputs){
Class<? extends Object> ownerClass = test.getClass();
Class<? extends Object> inputClass = input.getClass();
//Method method; //not needed
try {
ownerClass.getDeclaredMethod("add", inputClass).invoke(test, input);
} catch (NoSuchMethodException | SecurityException |
IllegalAccessException | IllegalArgumentException |
InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
I used these readings to help guide my answer, but altered the way I invoked the method:
http://tutorials.jenkov.com/java-reflection/methods.html
public class Test {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
Test testExample = new Test();
testExample.testMethod("String1", 1, "String2");
}
public void testMethod(Object... inputs) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
InputManipulation test = new InputManipulation();
for (Object input: inputs){
Class ownerClass = test.getClass();
Class inputClass = input.getClass();
Method method = ownerClass.getDeclaredMethod("add", inputClass);
method.invoke(test, input);
}
}
}
Your problem was caused by this method.invoke(test, "Testing reflection");
You iterate through 2 types of arguments and depends of this argument you invoke method 'add'. When you tried to invoke method with argument Integer you pass to method String parameter that causes error
Lets assume the following JUnit test class:
#RunWith(Parameterized.class)
public class MyTestClass {
private ExpensiveObjectToCreate myObject;
#Parameters
public static Collection<Object[]> data() {
Object[][] data = new Object[][] {
{ "parameter1" },
{ "parameter2" },
};
return Arrays.asList(data);
}
#Test
public void test1() {
}
#Test
public void test2() {
}
public MyTestClass(String stringParameter) {
myObject = new ExpensiveObjectToCreate(stringParameter);
}
}
Is there any way for me to create the expensive object just once for every parameter set? I say this because JUnit creates a new test class for every test it needs to run. This means that the expensive object is NOT created 2 times, but actually 4 times (2 parameter sets x 2 tests). This gets even worse when we have many test methods.
Also, sending the expensive object as a parameter is not a solution for me because my scenario is a little bit more complicated (I create the expensive object in JUnit rules).
Why not just roll out a custom cacher in your test case class, which caches the instance created per parameter and returns the same instance on further invocations.
#RunWith(Parameterized.class)
public class Test {
private static ExpensiveObjectCacher cacher; //instance which caches parameter instance
private ExpensiveObject myObject;
public Test(String value) {
this.myObject = cacher.get(value);
}
#BeforeClass
public static void setUpBeforeClass(){
cacher = new ExpensiveObjectCacher();
}
#Parameters
public static Collection<Object[]> data() {
Object[][] data = new Object[][] {
{ "parameter1" },
{ "parameter2" },
};
return Arrays.asList(data);
}
#org.junit.Test
public void test1(){
}
#org.junit.Test
public void test2(){
}
}
//caching for test cases.
class ExpensiveObjectCacher{
private Map<String, ExpensiveObject> map = new ConcurrentHashMap<String, ExpensiveObject>();
ExpensiveObject get(String value){
ExpensiveObject instance = map.get(value);
if(instance == null){
instance = new ExpensiveObject(value);
map.put(value, instance);
}
return instance;
}
}
class ExpensiveObject{
public ExpensiveObject(String value) {
System.out.println("Instance created: " + value);
}
}
Output:
Instance created: parameter1
Instance created: parameter2
You could work with a static Map from the parameters (here a simple string) to instances of ExpensiveObjectToCreate.
#RunWith(Parameterized.class)
public fnial class MyTestClass {
private static final Map<Parameter, ExpensiveObjectToCreate> MAPPING = new HashMap<>();
private ExpensiveObjectToCreate myEOTC;
public MyTestClass(String stringParameter) {
myEOTC = getEOTC(new Parameter(stringParameter));
}
private static getEOTC(Parameter parameter) {
ExpensiveObjectToCreate eotc = MAPPING.get(parameter);
if (eotc == null) {
eotc = new ExpensiveObjectToCreate(parameter.stringParameter);
MAPPING.put(parameter, eotc);
}
rturn eotc;
}
private static final class Parameter {
String stringParameter;
Parameter(String stringParameter) { this.stringParameter = stringParameter; }
#Override public int hashCode() { ... }
#Override public boolean equals(Object other) { ... }
}
}
However, if you also need to limit the number of expensive objects, you should do more work, for example a cache could be a solution.
If you're using Junit 4:
private static ExpensiveObjectToCreate myObject;
private static String stringParameter = "some text";
#BeforeClass
public static void setUpBeforeClass() throws Exception {
myObject = new ExpensiveObjectToCreate(stringParameter);
}
If Junit 3:
private static ExpensiveObjectToCreate myObject;
private static String stringParameter = "some text";
#BeforeClass
protected static void setUpBeforeClass() throws Exception {
myObject = new ExpensiveObjectToCreate(stringParameter);
}
In both cases the object will be created once for all the unit tests.
Edit: The String I am not sure where it came from, so I am asuming that the String is the same for all unit tests.
I am making a bukkit plugin, and I am using an API called MCStats, to create the graph, you add Plotters like so...
mobs.addPlotter(new Metrics.Plotter("Player") {
#Override
public int getValue() {
return 0;
}
});
But I want to get the values from a HashMap, and idealy something like this...
for(String mob: mobNames) {
mobs.addPlotter(new Metrics.Plotter(mob) {
#Override
public int getValue() {
return Stats.getValue(mob);
}
});
}
But obviously, it can't access the mob variable, if I set it to final, it still wont be able to change in the loop. How can I work around this problem?
You can, in fact, use final in an enhanced for loop:
for(final String mob: mobNames) {
mobs.addPlotter(new Metrics.Plotter(mob) {
#Override
public int getValue() {
return Stats.getValue(mob);
}
});
}
You can use the final keyword for mob and it still be changed in the loop.
Try to run this code below:
public class Test2 {
public static void main(String args[]) {
String[] data = new String[] {"1", "2"};
List<MyClass> test = new ArrayList<MyClass>();
for (final String word: data) {
test.add(new MyClass() {
#Override
public void testMethod() {
System.out.println(word);
}
});
}
for (MyClass myClass: test) {
myClass.testMethod();
}
}
static class MyClass {
public void testMethod() {
}
}
}
The output will be "1" and "2".