I was using a library called Mallet. It is by far the most complicated Java Library I have ever used. They provide tutorials and code template and I was trying to understand it. However, I came across this line of code:
TransducerEvaluator evaluator = new MultiSegmentationEvaluator(
new InstanceList[]{trainingData, testingData},
new String[]{"train", "test"}, labels, labels) {
#Override
public boolean precondition(TransducerTrainer tt) {
// evaluate model every 5 training iterations
return tt.getIteration() % 5 == 0;
}
};
Please don't pay too much attention on the term "transducer". What is passed into this function? Two classes? What is this new String[]{}? I am just very very confused with this syntax as I have never seen it before.
This is the code for this method:
public MultiSegmentationEvaluator (InstanceList[] instanceLists, String[] instanceListDescriptions,
Object[] segmentStartTags, Object[] segmentContinueTags)
Can someone tell me what this weird construct is?
This construct does several things:
Creates a subclass of MultiSegmentationEvaluator without giving it a name
Provides an override of the precondition(TransducerTrainer tt) method
Instantiates the newly defined anonymous class by passing two string arrays and then labels to the constructor that takes four parameters.
Assigns the newly created instance to the evaluator variable.
The code uses the anonymous class feature of Java - a very handy tool for situations when you have to subclass or implement an interface, but the class that you define is used in only one spot in your program.
Consider this code:
String[] stringArr = new String[]{"train", "test"};
Does it make any sense now? It is a String array! =) Here's even more stupid code to prove my point:
new String[]{"train", "test"}.getClass() == String[].class
InstanceList[]
means that you need to have a list of objects that are of they type InstanceList, same goes for String[]
for these:
Object[]
means that anything that is a sublass of Object (any object) can be passed as arguments for the last two paramaters.
In the top code this is exactly what they're doing but they create new objects for InstanceList and String,and then labels is the 2 objects they're passing.
Related
This might be a trivial question, but I need some clarification...
There is a book called Clean Code that says that our methods should be small, preferably up to 5-10 lines long. In order to achieve that we need to split our methods into smaller ones.
For instance, we may have someMethod() shown below. Let's say, modification of 'Example' takes 5 lines and I decide to move it into a separate method, modify 'Example' there and return it back to someMethod(). By doing this, someMethod() becomes smaller and easier to read. That's good, but there is a thing called "side effects" which says that we shouldn't pass an object to another method and modify it there. At least, I was told that it's a bad idea ) But I haven't seen anything prohibiting me from doing so in Clean Code.
public Example someMethod() {
// ... different lines here
Example example = new Example();
example = doSomethingHere(example, param1, param2, ...);
// ... different lines here
return example;
}
private Example doSomethingHere(Example example, 'some additional params here') {
// ... modify example's fields here ...
return example;
}
So, am I allowed to split the methods this way or such a side effect is prohibited and instead I should deal with a rather long-line method that definitely breaks Clean Code's rules talking about short methods?
UPDATED (more specific name for the sub-method)
public Example someMethod() {
// ... different lines here
Example example = new Example();
example = setExampleFields(example, param1, param2, ...);
// ... different lines here
return example;
}
private Example setExampleFields(Example example, 'some additional params here') {
// ... modify example's fields here ...
return example;
}
As JB Nizet commented, it's not actually a side effect if it's the only effect, so any blanket statement that "all side effects are bad" doesn't apply here.
Still, the main question stands: Is this (side) effect okay?
Talking about the principles first, side effects are, in general, dangerous for two reasons:
they make concurrency more difficult
they obscure/hide information
In your example, there is some information that is hidden. You could call this a potential side effect, and it can be exposed with a question: "Does this doSomethingHere method create a new object or modify the one I pass in?"
The answer is important, and even more so if it's a public method.
The answer should be trivial to find by reading the doSomethingHere method, especially if you're keeping your methods 'clean', but the information is nonetheless hidden/obscured.
In this specific case, I would make doSomethingHere return void. That way there's no potential for people to think that you've created a new object.
This is just a personal approach - I'm sure that plenty of developers say you should return the object you modify.
Alternatively, you can pick a 'good' method name. "modifyExampleInPlace" or "changeSomeFieldsInPlace" are pretty safe names for your specific example, imo.
we shouldn't pass an object to another method and modify it there.
Who says that? That is actually a good practice in order to split your function in a way that forms a "recipe" and have specific functions that know exactly how to populate your object properly.
What is not recommended (and probably the source where you got your recommendation misunderstood this rule) is defining a public API and modify the arguments. Users appreciate not having their arguments modified as it leads to less surprises. An example of that is passing arrays as arguments to methods.
When you define an object and pass it to an other method, method itself can modify the content of the object therein which may be unwanted in some cases. This is because you pass the reference(shallow copy) of the object to that method and method can modify that object.For example when you pass an Array, Arrays are objects, to a method, method can change the content of the Array which may not be what the caller method expects.
public static void main(String[] args){
int[] arr= {1,2,3,4};
y(arr);
//After the method arr is changed
}
public void y(int[] comingArray){
comingArray[0] = 10;
}
To make sure the values of Array cannot be changed, deep copy of the Array should be sent to method which is another story
However this is not the case when you use primite types(int, float etc.)
public static void main(String[] args){
int a= 1
y(a);
//After the method a is not changed
}
public void y(int comingInt){
comingInt = 5;
}
Due to the nature of the Objects, you should be carefulTo learn more about shallow copy and deep copy https://www.cs.utexas.edu/~scottm/cs307/handouts/deepCopying.htm
NOTE: This question is primarily theoretical; I've since given up on using this immediately, as everything I've thought up overcomplicates my code and smells a little like an antipattern. However, I find it interesting in theory and would love the community's help with it.
I'm refurbing some code written around the turn of the century for image manipulation; beginning by chopping apart a single class with a lot of redundancies into a number of BiFunction filters. They each accept a BufferedImage and an intensity (Double), and return a new BufferedImage. Of course, a lot of these image filters have additional concerns, like radius-of-effect or another intensity, and if I'm going to chain them efficiently, I would like to be able to set these as "uniforms" (or quasi-constants) before use.
My current method is simply to extend my ImageFilter class further, and set the uniforms as Bean-style properties. What I initially thought of doing was constraining them to a generic class that was held in an interface, and having something along the lines of:
public void addProperty(Uniform<T> property, T type)
in there, where T is specified entirely by the Uniform.
The original class kept all of these uniforms in a HashMap by String name, but that's the beginning of a lot of bad habits and I clean it up every time I see it. If a misspelling causes code to misfire, it's irresponsible code. I would prefer to just use a Singleton there, like a grown up.
So, in summary, is it possible in Java to bind a parameter type to the generic of another parameter? If so, how? If not, does anyone know of any plans to extend Java Generics in the future, in such a manner?
Thanks for any input!
Yes it's possible all we have to do is define the type parameter on the method itself. Check the example below.
public class Uniform {
}
public class ImageFilter {
//store in a list which can store any type of Uniform
List<Uniform<?>> uniformList = new ArrayList<Uniform<?>>();
//store in a map which can store any type of uniform and uses type as key
Map<Class<?>, Uniform<?>> uniformMap = new HashMap<>();
//Type parameter 'T' on the method itself
public <T> void addProperty(Uniform<T> property, T type) {
uniformList.add(property);
uniformMap.put(type.getClass(), property);
}
}
{
//sample usage
new ImageFilter().addProperty(new Uniform<>(), "test");
new ImageFilter().addProperty(new Uniform<>(), new Double(2.0));
}
Following is sample usage
new ImageFilter().addProperty(new Uniform<>(), "test");
//or
new ImageFilter().addProperty(new Uniform<String>(), "test");
//if for some reason JVM can't infer the type itself, it can be set manually
new ImageFilter().<String>addProperty(new Uniform<String>(), "test");
See this link for more information.
This is my main class MainClass and it has an arraylist MyList. I created an object for ExtractClass [not shown] extract and added it to my MyList. There is also another class PressClass [not shown]
public class MainClass {
public static void main(String[] args) {
ArrayList<ExtractClass> MyList = new ArrayList<ExtractClass>();
ExtractClass Extract = new ExtractClass();
MyList.add(Extract);
MyList.add(Extract);
PressClass Press = new PressClass();
Press.pressMethod(MyList);
}
}
Here is another version of the above program. I have initialized an object Extract and then added to MyList and i repeated it once more.
public class trailclass {
public static void main(String[] args) {
ArrayList<ExtractClass> MyList = new ArrayList<ExtractClass>();
ExtractClass Extract;
Extract = new ExtractClass();
MyList.add(Extract);
Extract = new ExtractClass();
MyList.add(Extract);
PressClass Press = new PressClass();
Press.pressMethod(MyList);
}
}
I got the same output for both programs. What is the difference between both? Does any of the above two codes breaks the rules of java? As a developer, which piece of code does one prefer?
It depends on what you try to achieve...
In the first snippet you are adding the same ExtractClass instance twice to the list and in the second code snippet you are adding 2 different ExtractClass instances to the list. As I am not aware to the internals of your ExtractClass I can determine which of the codes is "right".
Simple answer is that you are creating two objects, one of which you don't need. The garbage collector wont destroy it however because it is in the ArrayList MyList so a reference to it is still reachable.
In the first example the same object is being added to an ArrayList twice. In the second example, an object is made and added to to the ArrayList. After that, a new object is created and it too is added tot he ArrayList. The objects may have the same values (However you made your constructor) but the references are different.
If you want more explanation please ask.
What is the difference between both?
Firt one creates one single object and add it twice to the list
In the second you create two different(1) objects and add each one once to the list, this is what actualy you will in most cases intend to do.
Does any of the above two codes breaks the rules of java?
Technically not. List allows the same object to appear more than one time in it. Semantically, it depends whether it is your intetion to have the same object more than one time in the list or not.
As a developer, which piece of code does one prefer?
In general you mean the have the second version.
(1) different depends on your implementation of hashCode and equals. The defaults from the base class Object just dows a reference check. So the different instances will not be equal and thus different. You can see the impact of this when you use the List#contains method. Depending on your implementation of the former methods and on which instance you pass to it you may get different results.
The presented 2 solutions are not the same. The first adds the same object twice to the list while the second adds 2 different instances to the list.
Btw initializing a local variable in the same line is more compact and you should prefer that if it is a simple object creation:
ExtractClass Extract = new ExtractClass();
Also note that if you don't use the local variable, you can simply leave that out and add directly to the list:
MyList.add(new ExtractClass());
Also by convention you should start your variable names with lowercased letters and start your types (e.g. class name) with uppercased letter.
As per your current Implementation Both programs would work because you are adding object new ExtractClass()
with default implemnentation in the list. First program adds same object twice while the second adds 2 different instances to the list.
If you have scenario where ExtarctClass constructor accepts some parameter lets say File destDir you will be left with second Option because you may have to provide different destDir for different objects
with said above your second program would look like below
public class trailclass {
public static void main(String[] args) {
ArrayList<ExtractClass> MyList = new ArrayList<ExtractClass>();
ExtractClass Extract;
Extract = new ExtractClass(new File("c:\temp"));
MyList.add(Extract);
Extract = new ExtractClass(new File("c:\temp"));
MyList.add(Extract);
PressClass Press = new PressClass();
Press.pressMethod(MyList);
}
}
This can further be written as below
public class trailclass {
public static void main(String[] args) {
ArrayList<ExtractClass> MyList = new ArrayList<ExtractClass>();
MyList.add(new ExtractClass(new File("c:\temp")));
MyList.add(new ExtractClass(new File("c:\temp")));
PressClass Press = new PressClass();
Press.pressMethod(MyList);
}
}
Pretty new to Java
I would like to be able to use a method in following sort of way;
class PairedData {
String label;
Object val:
}
public void myMethod(String tablename, PairedData ... pD) {
/*
insert a record into a table -tablename with the various fields being
populated according to the information provided by the list of
PairedData objects
*/
}
myMethod("firststring",{"field1",Date1},{"field2",12},{"field3","aString"});
I realise the syntax is not valid but I hope it gives the gist of what I would like to do.
What I am trying to do is to directly pass the data rather than populate the instances of the class and then pass those. Is that possible or am I just trying to break a whole lot of OOPs rules?
No, what you're trying to do really isn't possible. It looks to me like it would be much better to pass instances of your class to the method as opposed to doing something convoluted with arrays like that. Another answer suggested using an Object[] varargs parameter - that's probably the closest you'll get to achieving something like what you show in your example. Another alternative (and I think a better one) would be
public void myMethod(String tablename, String[] labels, Object[] vals) {
You could instantiate your class for each labels[i] and vals[i] (pairing them up) in those arrays. In other words, in your method you could have something like
pD = new PairedData[labels.length];
for (i = 0; i < labels.length; i++)
pD[i] = new PairedData(labels[i], vals[i]); // assuming you
// added this
// constructor
The method call example that you included would then be converted to
myMethod("firststring", new String[]{"field1", "field2", "field3"},
new Object[]{date1, 12, "aString"});
You can do this by using arrays of Object:
public void myMethod(String tableName, Object[] ...pairs)
and invoke this method in a such style:
myMethod("someTable", new Object[] {"field1", date1}, new Object[] {"field2", date2});
usually...
you would make a class that has variable in it for all the parameters.
then you would build an instance of that class and populate the values.
then you could use that class instance to pass those around.
if you want a whole bunch... then make a Collection (Map, HashMap, List etc.) and pass that.
Seems to be a good case for a future language extension if you ask me. But by slightly changing the way you call your method we should be able to get close ...
myMethod("someTable",
new PairedData("field1", date1),
new PairedData("field2", date2)
);
It’s more type-work, but it is probably the safest as it is typesafe and not error prone to matching pairs.
You would also be required to write your constructor for ‘PairedData(String label, Object val)‘ for which I advise to write multiple overloaded versions one for each type of val you plan to store.
I have a String array that contains names of method in the yyyyyy class
In the xxxxxx class I'm making a yyyyyy instance (say obj). Now I can call obj.function_name(), except I want to read function_name from the String array in a loop. Is this possible?
You can, using reflection. It is done by calling Yyyy.class.getMethod("methodName").invoke(someArgs)
You'd have to handle a bunch of exceptions, and your method must be public. Note that java coding conventions prefer methodName to method_name.
Using reflection, however, should be a last resort. You should be using more object-oriented techniques.
If you constantly need similar features, perhaps you can look at some dynamic language running on the java platform, like Groovy
It's possible using reflection, although you should probably question your design somewhat if you need that sort of behavior. Class.getMethod takes a String for the method name and returns a Method object, which you can then call .invoke on to call the method
These Javadoc pages should be helpful:
Class.getMethod
Method.invoke
Sample code (assuming the yyyyyy methods take one int argument, just to show argument passing):
yyyyyy obj = new yyyyyy();
String[] methodNames = {"foo", "bar", "baz"};
for(String methodName : methodNames) {
Method method = Class.forName("yyyyyy").getMethod(methodName, new Class[] {int.class});
method.invoke(obj, 4); // 4 is the argument to pass to the method
}