Testing ThreadLocal member variables - java

I have been trying to verify if the ThreadLocal members are indeed different in different threads.
This is my TestClass whose object I am sharing among multiple threads.
public class TestClass {
private static Set<Integer> setI;
private static ThreadLocal<Set<String>> setS;
public TestClass() {
Set<String> temp = new HashSet<String>();
for (int i=0; i<=4; i++) {
setI.add(i);
temp.add(Integer.toString(i));
}
setS.set(temp);
}
static {
setI = new HashSet<Integer>();
setS = new ThreadLocal<Set<String>>() {
protected Set<String> initialValue() {
return new HashSet<String>();
}
};
}
public static void addToIntegerSet(int i) {
synchronized(setI) {
setI.add(i);
}
}
public static void addToStringSet(String str) {
Set<String> sets = setS.get();
sets.add(str);
setS.set(sets);
}
}
the following is the class I use to test this out :-
package personal;
import java.util.*;
import personal.TestClass;
import java.lang.reflect.Field;
public class Test2 {
private static TestClass testObj;
private static Set<Set<String>> testStringSet;
private static Set<Set<Integer>> testIntegerSet;
static {
testObj = new TestClass();
testStringSet = new HashSet<Set<String>>();
testIntegerSet = new HashSet<Set<Integer>>();
}
private static void addToStringSet(Set<String> sets) {
synchronized(testStringSet) {
testStringSet.add(sets);
}
}
private static void addToIntegerSet(Set<Integer> sets) {
synchronized(testIntegerSet) {
testIntegerSet.add(sets);
}
}
private static int getTestIntegerSetSize() {
synchronized(testIntegerSet) {
return testIntegerSet.size();
}
}
private static int getTestStringSetSize() {
synchronized(testStringSet) {
return testStringSet.size();
}
}
private static class MyRunnable implements Runnable {
private TestClass tc;
private String name;
public MyRunnable(TestClass tc, int i) {
this.name = "Thread:- " + Integer.toString(i);
this.tc = tc;
}
#Override
public void run() {
try {
Field f1 = tc.getClass().getDeclaredField("setS");
Field f2 = tc.getClass().getDeclaredField("setI");
f1.setAccessible(true);
f2.setAccessible(true);
Set<String> v1 = (Set<String>)(((ThreadLocal<Set<String>>)(f1.get(tc))).get());
Set<Integer> v2 = (Set<Integer>) f2.get(tc);
addToIntegerSet(v2);
addToStringSet(v1);
} catch (Exception exp) {
System.out.println(exp);
}
}
}
public static void main(String[] args) {
for (int i=1; i<=2; i++) {
(new Thread (new MyRunnable(testObj,i))).start();
}
try {
Thread.sleep(5);
} catch (Exception exp) {
System.out.println(exp);
}
System.out.println(getTestStringSetSize());
System.out.println(getTestIntegerSetSize());
}
}
thus the 1st print statement should print out 2 and the second one should print out 1.
how ever the 1st print statement also prints out 1.
what is wrong ?

For a test class, I'd start with something much, much simpler. Just store a String or something in the ThreadLocal to start with, and avoid the reflection calls (setAccessible, etc.). Your issue is most likely in all of this extra code, and nothing due to the ThreadLocal itself.

Related

How to create generic code for objects of different types

I have an entity that has as children several lists of objects that, although they have different classes, all have the order attribute, in several parts I end up with repeated code, for example in one part I need to order the lists by that attribute and I cannot simplify because they are of different type.
The relevant part of the entity is this:
contenido={
"educaciones":[
{
...
"orden":0
},{
...
"orden":1
}
],
"experiencias":[
{
...
"orden":0
},{
...
"orden":1
}
]
},
...
The code I would like to simplify:
if(tipo.equals("experiencias")){
List<Experiencia> iterable=contenido.getExperiencias();
for(int i = 0; i < iterable.size(); i++){
iterable.get(i).setOrden( orden.get(i) ); //orden = [0,3,5,...]
}
iterable.sort((it1,it2)-> it1.getOrden().compareTo(it2.getOrden()));
}else if(tipo.equals("educaciones")){
List<Educacion> iterable=contenido.getEducaciones();
for(int i = 0; i < iterable.size(); i++){
iterable.get(i).setOrden( orden.get(i) );
}
iterable.sort((it1,it2)-> it1.getOrden().compareTo(it2.getOrden()));
}else if...
Is there a way to create a code that is more generic and supports different objects?
Create an interface for the methods that are common between all you classes:
interface HasOrden {
int getOrden();
void setOrden(int i);
}
Each of your classes needs to implement HasOrden.
Then you can declare sortOrden function:
import java.util.ArrayList;
import java.util.List;
interface HasOrden {
int getOrden();
void setOrden(int i);
}
class Experiencia implements HasOrden {
private final String name;
int orden;
public Experiencia(String name) {
this.name = name;
}
#Override
public int getOrden() {
return orden;
}
#Override
public void setOrden(int i) {
orden = i;
}
public String toString() {
return name;
}
}
public class Eg {
static void sortOrden(List<? extends HasOrden> l, List<Integer> order) {
if (l.size() != order.size()) {
throw new RuntimeException("length mismatch");
}
for (int i = 0; i < l.size(); i++) {
l.get(i).setOrden(order.get(i));
}
l.sort((it1,it2)-> Integer.compare(it1.getOrden(), it2.getOrden()));
}
public static void main(String[] args) {
List<Experiencia> items = new ArrayList<>(List.of(new Experiencia("a"), new Experiencia("b")));
List<Integer> order = List.of(2,1);
sortOrden(items, order);
System.out.println(items);
}
}
You can call sortOrden on any list of HasOrden instances.
you can try to create a List<?> - list with a dynamic type outside of your if else block and move your duplicated code outside too and at the end of the if else block. In addition, you have to create a common class or some interface for your classes, which holds all the common field you needed
public class Main {
public static class Something {
private Integer sth;
public Integer getSth() {
return sth;
}
public void setSth(Integer sth) {
this.sth = sth;
}
}
public static class ThisClass extends Something {
private Integer num;
public ThisClass(Integer num) {
this.num = num;
}
public Integer getNum() {
return num;
}
public void setNum(Integer num) {
this.num = num;
}
}
public static class ThatClass extends Something {
private String str;
public ThatClass(String str) {
this.str = str;
}
public String getStr() {
return str;
}
public void setNum(String str) {
this.str = str;
}
}
public static List<? extends Something> sortList(Class<?> itemClass, List<? extends Something> list)
throws Exception {
for(int i = 0; i < list.size(); i++){
list.get(i).setSth(i);
}
list.sort((it1,it2)-> it1.getSth().compareTo(it2.getSth()));
return list;
}
public static void main(String[] args) {
System.out.println("Hello World");
List<? extends Something> someList = new ArrayList<>();
boolean check = true;
if(check) {
someList = Arrays.asList(new ThisClass(1),new ThisClass(1),new ThisClass(1),new ThisClass(1));
} else {
someList = Arrays.asList(new ThatClass("a"), new ThatClass("a"),new ThatClass("a"),new ThatClass("a"));
}
try {
someList = sortList(ThisClass.class, someList);
for(int i = 0; i < someList.size(); i++){
System.out.println(someList.get(i).getSth());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

How can we write code having loop, if/else and return statement using java streams

I need to use java streams for this piece of code.
for(int i =0 ;i< maxWaitTimeForRegistration ; i++) {
if (service.getRefreshDeviceDetails(BaseTest.equalsIgnoreCase("Disconnected")) {
return true;
}
WaitinSeconds(5);
}
I tried using this
IntStream.range(0, maxWaitTimeForRegistration).forEach(j -> {
if (service.getRefreshDeviceDetails(BaseTest.equalsIgnoreCase("Disconnected")) {
return true;
}
WaitinSeconds(5);
}
});
But since forEach method is returning void, so It's not right.
Technically it could be done this way:
private static boolean retryStream() {
return IntStream.range(0, MAX_WAIT_TIME_FOR_REGISTRATION)
.peek(tryNum -> waitSeconds(4))
.anyMatch(tryNum -> service.getRefreshDeviceDetails(BaseTest.equalsIgnoreCase("Disconnected")));
}
But the Stream API is not really intended for blocking retries. Also, this way the stream is waiting even before the first check... so you would probably need to use another if condition check before the stream retry.
A working soution:
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
class Scratch {
private static final int MAX_WAIT_TIME_FOR_REGISTRATION = 4;
private static final Service service = new Service();
private static String BaseTest = "Test";
public static void main(String[] args) {
// change the value asynchronously
new Thread(() -> {
waitSeconds(4 * 2);
BaseTest = "Disconnected";
}).start();
// System.out.println(retry());
System.out.println(retryStream());
}
private static boolean retry() {
for(int i = 0; i< MAX_WAIT_TIME_FOR_REGISTRATION; i++) {
if (service.getRefreshDeviceDetails(BaseTest.equalsIgnoreCase("Disconnected"))) {
return true;
}
waitSeconds(4);
}
return false;
}
private static boolean retryStream() {
return IntStream.range(0, MAX_WAIT_TIME_FOR_REGISTRATION)
.peek(tryNum -> waitSeconds(4))
.anyMatch(tryNum -> service.getRefreshDeviceDetails(BaseTest.equalsIgnoreCase("Disconnected")));
}
private static void waitSeconds(int seconds) {
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(seconds));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
class Service {
public boolean getRefreshDeviceDetails(boolean disconnected) {
return disconnected;
}
}

Java Runnable as argument evaluation

I am developing a client-server in java and I encountered problem passing a custom Runnable implementation as argument from an object to another.
The problem is that the Runnable code is evaluated (not executed) at definition but I want it to be evaluated at invocation.
Is there any way to achieve this behavior?
Here the code affected by this problem:
Custom Runnable implementation
public abstract class ChallengeReportDelegation implements Runnable
{
private ChallengeReport fromChallengeReport = null;
private ChallengeReport toChallengeReport = null;
#Override
public abstract void run();
public ChallengeReport getFromChallengeReport()
{
return fromChallengeReport;
}
public ChallengeReport getToChallengeReport()
{
return toChallengeReport;
}
public void setFromChallengeReport(ChallengeReport fromChallengeReport)
{
this.fromChallengeReport = fromChallengeReport;
}
public void setToChallengeReport(ChallengeReport toChallengeReport)
{
this.toChallengeReport = toChallengeReport;
}
}
Here where the Runnable is passed as argument:
// Record challenge
this.challengesManager.recordChallenge(whoSentRequest, whoConfirmedRequest,
new ChallengeReportDelegation()
{
#Override
public void run()
{
ChallengeReport fromReport = getFromChallengeReport();
ChallengeReport toReport = getToChallengeReport();
sendMessage(whoSentRequest, new Message(MessageType.CHALLENGE_REPORT, String.valueOf(fromReport.winStatus), String.valueOf(fromReport.challengeProgress), String.valueOf(fromReport.scoreGain)));
sendMessage(whoConfirmedRequest, new Message(MessageType.CHALLENGE_REPORT, String.valueOf(toReport.winStatus), String.valueOf(toReport.challengeProgress), String.valueOf(toReport.scoreGain)));
}
});
The receiving object store the ChallengeReportDelegation instance as completionOperation, wait for a timeout then execute this code.
private void complete()
{
stopTranslations();
int fromStatus;
int toStatus;
if (this.fromScore > this.toScore)
{
fromStatus = 1;
toStatus = -1;
}
else if (this.fromScore < this.toScore)
{
fromStatus = -1;
toStatus = 1;
}
else
{
fromStatus = 0;
toStatus = 0;
}
this.completionOperation.setFromChallengeReport(new ChallengeReport(this.from, fromStatus,this.fromTranslationsProgress, this.fromScore));
this.completionOperation.setToChallengeReport(new ChallengeReport(this.to, toStatus, this.toTranslationsProgress, this.toScore));
this.completionOperation.run();
}
The code above raises a NullPointerException at the execution of the last portion of code, in the run method.
[EDIT]
The NullPointerException exception is thrown because both getFromChallengeReport() and getToChallengeReport() (second portion of code) initially return null (when the Runnable is defined and passed as argument),
but they would return consistent values at invocation time run() (third portion of code)
[EDIT2]
I reproduced the situation in this simple code:
public class TestEvaluation
{
public static void main(String[] args) throws InterruptedException
{
Middle middle = new Middle();
middle.register(new Task() {
#Override
public void run() {
System.out.println("a is: " + getA());
System.out.println("b is: " + getB());
}
});
Thread.sleep(2000);
}
abstract static class Task implements Runnable
{
private int a = 0;
private int b = 0;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}
#Override
abstract public void run();
}
static class Middle
{
private ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(1);
public void register(Task task)
{
Leaf leaf = new Leaf(new Task() {
#Override
public void run() {
System.out.println("Middle");
task.run();
}
});
pool.schedule(leaf, 1, TimeUnit.SECONDS);
}
}
static class Leaf implements Runnable
{
public Task task;
public Leaf(Task task)
{
this.task = task;
}
#Override
public void run()
{
task.setA(5);
task.setB(5);
System.out.println("Leaf");
task.run();
}
}
}
The behavior that i want to achieve is the printing of
Leaf
Middle
a is: 5
b is: 5
But this is what i get
Leaf
Middle
a is: 0
b is: 0
A very simple example. Lets create a runnable with a field.
public static void main (String[] args) {
var x = new Runnable(){
int a = 0;
int getA(){
return a;
}
void setA(int v){
a = v;
}
public void run(){
System.out.println("A : " + getA());
}
};
x.run();
x.setA(5);
x.run();
}
The first time it is 0, the second time 5, because getA is evaluated when run is called.
I found a working solution for this problem, perhaps trivial for those coming from functional programming.
Accordingly to the example in last edit ([EDIT2])
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
public class TestEvaluation
{
public static void main(String[] args) throws InterruptedException
{
Middle middle = new Middle();
middle.register(new Consumer<Values>() {
#Override
public void accept(Values values) {
System.out.println("a is: " + values.getA());
System.out.println("b is: " + values.getB());
}
});
Thread.sleep(2000);
}
static class Values
{
private int a = 0;
private int b = 0;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}
}
static class Middle
{
private ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(1);
public void register(Consumer<Values> passed)
{
Consumer<Values> middleConsumer = new Consumer<Values>() {
#Override
public void accept(Values values) {
System.out.println("Middle");
passed.accept(values);
}
};
Leaf leaf = new Leaf(middleConsumer);
pool.schedule(leaf, 1, TimeUnit.SECONDS);
}
}
static class Leaf implements Runnable
{
public Consumer<Values> task;
public Leaf(Consumer<Values> task)
{
this.task = task;
}
#Override
public void run()
{
Values values = new Values();
values.setA(5);
values.setB(5);
System.out.println("Leaf");
task.accept(values);
}
}
}
This code produces the behavior i want.
Hope this will help someone.
Cheers!
If you want to immediately evaluate something. I'd suggest not using a Runnable at all. It sound like an anti-pattern, trying to pass code around when all you want is the value/invocation.
Furthermore, try to use a Callable or Supplier instead since you are clearly interested in returning some values from the sub-routines.

How to Count Number of Instances of a Class

Can anyone tell me how to count the number of instances of a class?
Here's my code
public class Bicycle {
//instance variables
public int gear, speed, seatHeight;
public String color;
//constructor
public Bicycle(int gear, int speed, int seatHeight, String color) {
gear = 0;
speed = 0;
seatHeight = 0;
color ="Unknown";
}
//getters and setters
public int getGear() {
return gear;
}
public void setGear(int Gear) {
this.gear = Gear;
}
public int getSpeed() {
return speed;
}
public void setSpeed(int Speed){
this.speed = Speed;
}
public int getSeatHeight() {
return seatHeight;
}
public void setSeatHeight(int SeatHeight) {
this.seatHeight = SeatHeight;
}
public String getColor() {
return color;
}
public void setColor(String Color) {
this.color = Color;
}
}//end class
public class Variable extends Bicycle {
public Variable(int gear, int speed, int seatHeight, String color) {
super(gear, speed, seatHeight, color);
}
}//end class
public class Tester {
public static void main(String args[]){
Bicycle bicycle1 = new Bicycle(0, 0, 0, null);
bicycle1.setColor("red");
System.out.println("Color: "+bicycle1.getColor());
bicycle1.setSeatHeight(4);
System.out.println("Seat Height: "+bicycle1.getSeatHeight());
bicycle1.setSpeed(10);
System.out.println("Speed: "+bicycle1.getSpeed());
bicycle1.setGear(6);
System.out.println("Gear: "+bicycle1.getGear());
System.out.println("");//space
Bicycle bicycle2 = new Bicycle(0, 0, 0, null);
bicycle2.setColor("black");
System.out.println("Color: "+bicycle2.getColor());
bicycle2.setSeatHeight(6);
System.out.println("Seat Height: "+bicycle2.getSeatHeight());
bicycle2.setSpeed(12);
System.out.println("Speed: "+bicycle2.getSpeed());
bicycle2.setGear(6);
System.out.println("Gear: "+bicycle2.getGear());
System.out.println("");//space
}//end method
}//end class
The class variable is to be used to keep count of the number of instances of the Bicycle class created and the tester class creates a number of instances of the Bicycle class and demonstrates the workings of the Bicycle class and the class variable. I've looked all over the internet and I can't seem to find anything, could someone show me how to do it please, thanks in advance :)
Since static variables are initialized only once, and they're shared between all instances, you can:
class MyClass {
private static int counter;
public MyClass() {
//...
counter++;
}
public static int getNumOfInstances() {
return counter;
}
}
and to access the static field counter you can use MyClass.getNumOfInstances()
Read more about static fields in the JLS - 8.3.1.1. static Fields:
If a field is declared static, there exists exactly one incarnation of the field, no matter how many instances (possibly zero) of the class may eventually be created. A static field, sometimes called a class variable, is incarnated when the class is initialized (ยง12.4).
Note that counter is implicitly set to zero
Pleae try the tool of java
jmap -histo <PDID>
Out put
num #instances #bytes class name
----------------------------------------------
1: 1105141 97252408 java.lang.reflect.Method
2: 3603562 86485488 java.lang.Double
3: 1191098 28586352 java.lang.String
4: 191694 27035744 [C
In addition, you should override finalize method to decrement the counter
public class Bicycle {
...
public static int instances = 0;
{
++instances; //separate counting from constructor
}
...
public Bicycle(int gear, int speed, int seatHeight, String color) {
gear = 0;
speed = 0;
seatHeight = 0;
color ="Unknown";
}
#Override
protected void finalize() {
super.finalize();
--instances;
}
}
You should have in mind that static variables are CLASS scoped (there is no one for each instance, only one per class)
Then, you could demonstrate instance decrement with:
...
System.out.println("Count:" + Bicycle.getNumOfInstances()); // 2
bicycle1 = null;
bicycle2 = null;
System.gc(); // not guaranteed to collect but it will in this case
Thread.sleep(2000); // you expect to check again after some time
System.out.println("Count again:" + Bicycle.getNumOfInstances()); // 0
why not using a static counter?
public class Bicycle {
private static int instanceCounter = 0;
//instance variables
public int gear, speed, seatHeight;
public String color;
//constructor
public Bicycle(int gear, int speed, int seatHeight, String color) {
gear = 0;
speed = 0;
seatHeight = 0;
color ="Unknown";
instanceCounter++;
}
public int countInstances(){
return instanceCounter;
}
........
You just need static counter in class.
public class Bicycle {
private static volatile int instanceCounter;
public Bicycle() {
instanceConter++;
}
public static int getNumOfInstances() {
return instanceCounter;
}
protected void finalize() {
instanceCounter--;
}
}
As mentioned in many comments finalize() is not recommended to use so there could be another approach to count the Bicycle instances -
public class Bicycle {
private static final List<PhantomReference<Bicycle>> phantomReferences = new LinkedList<PhantomReference<Bicycle>>();
private static final ReferenceQueue<Bicycle> referenceQueue = new ReferenceQueue<Bicycle>();
private static final Object lock = new Object();
private static volatile int counter;
private static final Runnable referenceCleaner = new Runnable() {
public void run() {
while (true) {
try {
cleanReferences();
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
static {
Thread t = new Thread(referenceCleaner);
t.setDaemon(true);
t.start();
}
private Bicycle() {
}
public static Bicycle getNewBicycle() {
Bicycle bicycle = new Bicycle();
counter++;
synchronized (lock) {
phantomReferences.add(new PhantomReference<Bicycle>(new Bicycle(), referenceQueue));
}
System.out.println("Bicycle added to heap, count: " + counter);
return bicycle;
}
private static void cleanReferences() {
try {
PhantomReference reference = (PhantomReference) referenceQueue.remove();
counter--;
synchronized (lock) {
phantomReferences.remove(reference);
}
System.out.println("Bicycle removed from heap, count: " + counter);
} catch (Exception e) {
e.printStackTrace();
}
}
public static int getNumOfBicycles() {
return counter;
}
}
public class BicycleTest {
public static void main(String[] args) {
int i = 0;
while (i++ < 1000) {
Bicycle.getNewBicycle();
}
while (Bicycle.getNumOfBicycles() > 0) {
try {
Thread.sleep(1000);
System.gc(); // just a request
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Alternatively, you can create a counter with an initializer block and a static variable.
class SomeClass
{
private static int instanceCounter;
{
instanceCounter++;
}
}
Initializer blocks get copied by the compiler into every constructor, so, you will have to write it once no matter how many constructors you will need (As referred into the above link). The block in {} runs every time you create a new object of the class and increases the variable counter by one.
And of course get the counter by something like:
public static int getInstanceCounter()
{
return instanceCounter;
}
or directly
int numOfInstances = SomeClass.instanceCounter;
If you do not make numOfInstances private
One basic approach is to declare a static numeric member field thats incremented each time the constructor is invoked.
public class Bicycle {
//instance variables
public int gear, speed, seatHeight;
public String color;
public static int bicycleCount = 0;
//constructor
public Bicycle(int gear, int speed, int seatHeight, String color) {
gear = 0;
speed = 0;
seatHeight = 0;
color ="Unknown";
bicycleCount++;
}
...
}
If you want to count and test instances based on the number of objects created, you can use a loop to see what really is happening. Create a constructor and use a static counter
public class CountInstances {
public static int count;
public CountInstances() {
count++;
}
public int getInstaces() {
return count;
}
public static void main(String []args) {
for(int i= 0; i<10; i++) {
new CountInstances();
}
System.out.println(CountInstances.count);
}
}
public class Number_Objects {
static int count=0;
Number_Objects(){
count++;
}
public static void main(String[] args) {
Number_Objects ob1=new Number_Objects();
Number_Objects ob2=new Number_Objects();
Number_Objects obj3=new Number_Objects();
System.out.print("Number of objects created :"+count);
}
}

Delegating method calls using variable number of arguments

This question came up in the course of my work programming; it's become irrelevant to the current task, but I'm still curious if anyone has an answer.
In Java 1.5 and up you can have a method signature using a variable number of arguments, with an ellipsis syntax:
public void run(Foo... foos) {
if (foos != null) {
for (Foo foo: foos) { //converted from array notation using autoboxing
foo.bar();
}
}
}
Suppose I want to do some operation on each foo in the foos list, and then delegate this call to some field on my object, preserving the same API. How can I do it? What I want is this:
public void run(Foo... foos) {
MyFoo[] myFoos = null;
if (foos != null) {
myFoos = new MyFoo[foos.length];
for (int i = 0; i < foos.length; i++) {
myFoos[i] = wrap(foos[i]);
}
}
run(myFoos);
}
public void run(MyFoo... myFoos) {
if (myFoos!= null) {
for (MyFoo myFoo: myFoos) { //converted from array notation using autoboxing
myFoo.bar();
}
}
}
This doesn't compile. How can I accomplish this (passing a variable number of MyFoo's to the run(MyFoo...) method)?
Is this what you want?
public class VarArgsTest {
public static class Foo {}
public static class MyFoo extends Foo {
public MyFoo(Foo foo) {}
}
public static void func(Foo... foos) {
MyFoo [] myfoos = new MyFoo[foos.length];
int i=0;
for (Foo foo : foos) {
myfoos[i++] = new MyFoo(foo);
}
func(myfoos);
}
public static void func(MyFoo... myfoos) {
for (MyFoo m : myfoos) {
System.out.println(m);
}
}
public static void main(String [] args) throws Exception {
func(new Foo(), new Foo(), new Foo());
}
}
I tried it and did NOT get a compile error. What is the actual error you are seeing? Here is the code I used. Perhaps i did something different:
public class MultipleArgs {
public static void main(String [] args){
run(new Foo("foo1"), new Foo("foo2"), new Foo("foo3"));
}
public static void run(Foo... foos){
MyFoo[] myFoos = null;
if (foos != null) {
myFoos = new MyFoo[foos.length];
for (int i = 0; i < foos.length; i++) {
myFoos[i] = wrap(foos[i]);
}
}
run(myFoos);
}
public static void run(MyFoo... myFoos){
if (myFoos!= null) {
for (MyFoo myFoo: myFoos) {
myFoo.bar();
}
}
}
private static class Foo {
public final String s;
public Foo(String s){
this.s = s;
}
#Override
public String toString(){
return s;
}
}
private static class MyFoo{
private final String s;
public MyFoo(String s){
this.s = s;
}
public void bar(){
System.out.println(s);
}
#Override
public String toString(){
return s;
}
}
private static MyFoo wrap(Foo foo){
return new MyFoo(foo.s);
}
}
This doesn't answer your question; it's incidental, but you don't need the null test. Here's proof:
public class VarargsTest extends TestCase {
public void testVarargs() throws Exception {
assertEquals(0, fn());
}
private int fn(String...strings) {
return strings.length;
}
}
If the method is called without any arguments, the varargs list is an empty array, not null.
I think the actual solution to your question would be to rename the second function.
use java reflections.

Categories