Call functions put in array - java

for my code in Java I need to call functions for some figures inside a number. In fact, if my number is 464, I have to call functions named assert4 and assert6. I hope that you're understanding. But if I'm right, we can't concatenate a string and a variable to have the name of a function and execute it. For example :
for (int i = 0; i < number.length(); i++) {
assert + i + (); // For example executing the function assert4
}
So I can't see how I can do it. Thanks for help !

You can do this with reflection using something like YourClass.class.getMethod(...).invoke(...). (See this question for instance.)
However, this is a bit of a code smell and I encourage you to do something like
Map<Integer, Runnable> methods = new HashMap<>();
methods.put(464, YourClass::assert464);
...
for (int i = 0; i < number.length(); i++) {
methods.get(i).run();
}
If you're on Java 7 or older, the equivalent would be
methods.put(464, new Runnable() { public void run() { assert464(); } });

You can call a method using a String name using the reflection API.
Here's some tutorials on how to get started:
http://docs.oracle.com/javase/tutorial/reflect/
http://www.ibm.com/developerworks/library/j-dyn0603/

Related

How can I change code based on Method Argument?

public static void calculate(List<Person> data, String categoryType) {
for(int i = 0; i < categoryData.size(); i++) {
if(data.get(i).calculateCategoryOne() == firstPlace) {
...
}
}
}
If you see data.get(i).calculateCategoryOne(), the method call is for category one. The problem is that I need to copy-paste the entire code in a if-block for each category to just change this method call data.get(i).calculateCategoryTwo(), data.get(i).calculateCategoryThree(), ... data.get(i).calculateCategoryTen(),
While I can still make the logic work in this way, I feel it is redundant and not a good programming practice. Just to change one line of code, I would have to replicate the same code ten different times which will add nearly 500 lines of code.
So, my question is: Is there a way to dynamically change my method call based on the category type string argument.
I was thinking one possible way is to pass the method call in a string and convert it to a method call itself. For example, let's assume CategoryType string argument is "calculateCategoryOne()". So, data.get(i)."calculateCategoryOne()" would be recognized by the compiler as the method call itself. Is there a way to actually implement this?
I'm open to other ideas as well to reduce redundancy.
I would think using a functional interface would be appropriate here. You want different functionality depending on the categoryType, so passing in the function you want to use, rather than a String representation of it, would accomplish this.
#FunctionalInterface
public interface Calculate {
int calculate(Person data);
}
public static void calculate(List<Person> data, Calculate calculate) {
for(int i = 0; i < categoryData.size(); i++) {
if(calculate.calculate(data.get(i)) == firstPlace) {
...
}
}
}
and the call to the method would define what the calculation would be
calculate(list, p -> {
// calculation done here
});
or if this would happen frequently, you could predefine your categories once and pass those in:
Calculate categoryOne = p -> { ... };
Calculate categoryTwo = p -> { ... };
.
.
calculate(list, categoryOne);

How can I define new init in swift?

I need the code written here, I could not to paste here
https://www.geeksforgeeks.org/length-smallest-sub-string-consisting-maximum-distinct-characters/
i need it in swift
Although it's not recommended, But you can define a global constant and use it anywhere you like:
// At the top level, outside of any class or etc.
let NO_OF_CHARS = 256
Update due to question change:
C style for is deprecated in Swift (since v3 I think), you should convert the syntax to Swift like this:
/*
for (int i = 0; i < n; i++) {
}
*/
// Will be like
for i in 0...n {
}

PJSUA2 Java - How to get ongoing Call's AudioMedia

I'm using the Java library for PJSUA / PJSIP and i'm trying to get the AudioMedia for an answered call but its not working. I've followed the C++ documentation (no Java doc for answering calls) which has led me to the following implementation:
public void onCallMediaState(OnCallMediaStateParam param) {
CallInfo ci = this.getInfo();
for(int i = 0; i < ci.getMedia().size(); i++) {
if(ci.getMedia().get(i).getType() == pjmedia_type.PJMEDIA_TYPE_AUDIO) {
AudioMedia aum = (AudioMedia) this.getMedia(i);
}
}
}
The first part works, it finds a media in the call info with type PJMEDIA_TYPE_AUDIO, and if i check the type of this.getMedia(i) that is also PJMEDIA_TYPE_AUDIO. However when I try to cast it to type AudioMedia it fails to cast.
I assume the rest of SIP setup is working, as when I call the number, pjsua reports the incoming call and answers it, I'm just unable to get the AudioMedia to send/receive audio.
The documentation is for C++ but thus far it has been exactly the same for Java except for this part, Reference here. What am I doing wrong?
Found it!
AudioMedia has a static method typecastFromMedia(Media media) for casting to AudioMedia. I assume this is because the casting has to occur in the underlying C++ implementation so you can't just do a high-level java cast.
Working example:
public void onCallMediaState(OnCallMediaStateParam param) {
CallInfo ci = this.getInfo();
for(int i = 0; i < ci.getMedia().size(); i++) {
if(ci.getMedia().get(i).getType() == pjmedia_type.PJMEDIA_TYPE_AUDIO) {
AudioMedia aum = AudioMedia.typecastFromMedia(this.getMedia(i));
}
}
}
You can using getAudioMedia() API to get AudioMedia, my simple onCallMediaState() in
SipCall(subclass of Call class) using C++:
void SipCall::onCallMediaState(OnCallMediaStateParam &prm) {
this->callInfo = getInfo();
unsigned media_size = this->callInfo.media.size();
for (unsigned i = 0; i < media_size; i++) {
AudioMedia audioMedia = getAudioMedia(i);
// do something
//...
}
}

Dynamic calling of JBehave steps from inside Java

In Java I have a String object that has the text that I wish to be matched and executed by JBehave as a step. How can this be done? Can it be done?
What I am really trying to do is to have a wrapper JBehave step that instruments another arbitrary JBehave step. It does a few things before and after calling on the "inner" step.
So lets say that I already have the following
When I say Hello World
and
#When("I say $text")
public void iSay(final String text)
{
System.out.println(text);
}
I want to be able to do the following :
When I repeat 4 times I say Hello World
it will call :
#When("I repeat $count times $subStepString")
public void repeat(final int repeatCount, final String subStepString)
{
// prep code here
for (int i = 0; i < repeatCount; i++)
{
howDoIdoThisBitHere(subStepString);
}
// post process code here
}
The part that says howDoIdoThisBitHere(...) should end up having JBehave match the value of subStepString as if it was encountered in the case above. This way I can use this method to call other arbitrary things.
I'm not sure this is a great idea since the step classes shouldn't have any dependency on the core configuration (StepMatchers, Runners etc.), but is this solution kind of what you're looking for?
#When("I repeat $count times $subStepString")
public void repeat(final int repeatCount, final String subStepString)
{
// prep code here
for (int i = 0; i < repeatCount; i++)
{
StoryParser sp = configuration().storyParser();
Story s = sp.parseStory(subStepString);
StoryRunner e = configuredEmbedder().storyRunner();
e.run(configuration(), configuredEmbedder().candidateSteps(), s);
}
}

Is there any difference between these two loops?

Is there any difference performance-wise between the two code snippets below?
for(String project : auth.getProjects()) {
// Do something with 'project'
}
and
String[] projects = auth.getProjects();
for(String project : projects) {
// Do something with 'project'
}
For me, I think the second one is better, but it is longer. The first one is shorter, but I am not really sure if it is faster. I am not sure, but to me it seems like every time that loop is iterated, auth.getProjects is called. Is that not so?
Edit: #StephenC is right, the JLS is a much better place to find an answer for something of this nature. Here is a link to the enhanced for loop in the language specification. In there you will find that there are a few different types of for statements it generates but none of them would call the method more than 1 time.
Simple test shows that the method is only called once
public class TestA {
public String [] theStrings;
public TestA() {
theStrings = new String[] {"one","two", "three"};
for(String string : getTheStrings()) {
System.out.println(string);
}
}
public String[] getTheStrings() {
System.out.println("get the strings");
return theStrings;
}
public static void main(String [] args) {
new TestA();
}
}
Output:
get the strings
one
two
three
So essentially they are the same thing. The only thing that may be beneficial about the 2nd would be if you want to use the array outside the for loop.
Edit
You got me curious about how the java compiler handled this so using the code above I decompiled the class file and heres what the result is
public class TestA
{
public TestA()
{
String as[];
int j = (as = getTheStrings()).length;
for(int i = 0; i < j; i++)
{
String string = as[i];
System.out.println(string);
}
}
public String[] getTheStrings()
{
System.out.println("get the strings");
return theStrings;
}
public static void main(String args[])
{
new TestA();
}
public String theStrings[] = {
"one", "two", "three"
};
}
As you can see the compiler simply restructured your for loop into a standard loop! It also further proves that in fact they are exactly the same after the compiler gets through with it.
Assumng that by in you mean :, there is no difference in performance; they both do the same thing. Even in the first example, auth.getProjects() is executed only once; it can't be executed multiple times, since if it was, the for iteration would have to start over each time, which is not how it works.
I'd recommend using the version you find to be clearer.
There are a few more operations in the second example. Instead of referencing the array directly using the method, you are declaring a new reference variable, storing it in that new variable, then referencing the new variable.
You can check out the bytecode with ASM Bytecode Outline.
BUT, this is micro-optimization. If you need a new reference variable, then create one. If you don't need one, save the work and don't create a new one.
There is no difference.
According to the JLS 14.14.2, an enhanced for loop (for an array type) is equivalent to a regular for loop with the following pattern:
T[] #a = Expression;
L1: L2: ... Lm:
for (int #i = 0; #i < #a.length; #i++) {
{VariableModifier} TargetType Identifier = #a[#i];
Statement
}
If we substitute for your first example:
for(String project : auth.getProjects()) {
// Do something with 'project'
}
we get:
String[] $a = auth.getProjects();
for (int $i = 0; $i < $a.length; $i++) {
String project = $a[$i];
// Do something with 'project'
}
For your second example:
String[] projects = auth.getProjects();
for(String project : projects) {
// Do something with 'project'
}
we get:
String[] projects = auth.getProjects();
String[] $a = projects;
for (int $i = 0; $i < $a.length; $i++) {
String project = $a[$i];
// Do something with 'project'
}
The two versions of the code are clearly equivalent, and assuming that javac or the JIT is capable of optimizing away the redundant local variable $a, the two versions should perform the same.
Note that the local variable $a is only created once at the start of the loop in both cases.
The second one is better performance-wise, it is not creating a variable multiple times. Therefore, yes, auth.getProjects is being called every time.
Both are same as found above.
But do one thing use 1st approcah and after the for loop, de-reference the projects variable as-
projects = null;
Else, it will stay alive for the complete method life and will consume unnecessary memory.

Categories

Resources