hi I'm rewriting a java code in C# and I'm stuck here:
public void printSolveInstructions() {
System.out.print(getSolveInstructionsString());
}
public String getSolveInstructionsString() {
if (isSolved()) {
return historyToString(solveInstructions);
} else {
return "No solve instructions - Puzzle is not possible to solve.";
}
}
public List<LogItem> getSolveInstructions() {
if (isSolved()) {
return Collections.unmodifiableList(solveInstructions);
} else {
return Collections.emptyList();
}
}
I know how to rewrite the first two methods (it's for referencing the last one) but I don't know the equivalent for Collections.unmodifiableList() and Collections.emptyList()
solveInstructions is of type List here's the declaration in java and C#:
private ArrayList<LogItem> solveInstructions = new ArrayList<LogItem>() // java
private List<LogItem> solveInstructions = new List<LogItem>() // c#
update
I rewrote the getSolveInstructions() method in this way:
public List<LogItem> getSolveInstructions()
{
if (isSolved())
{
return solveInstructions.AsReadOnly();
}
else
{
return new List<LogItem>();
}
}
Now the problem is ide gives me an error when I use .AsReadOnly()
Your method returns either a List<LogItem>, or an IReadOnlyCollection<LogItem> (produced by call to List<T>.AsReadOnly() method; however, your return type is List<LogItem>, which is incompatible with the IReadOnlyCollection<LogItem>. Change your method return type to IList<LogItem>, which works for both types.
Note, since this method can return either a read-only or a read-write list, calling code should check the returned collection's IsReadOnly property, before attempting to modify it.
Related
In my program I receive a message from a call, that has a variable of the type Optional and depending on whether something is inside of this variable or not I shall make a call of a method with a parameter or a call to the same method without a parameter, standard overloading.
The problem I am having is that the produced code becomes ugly, especially the more optionals I receive the more distinguishing the method call becomes. Currently the next method call is determined via an if-else.
Here is a simplified code for this question, first the Message Class:
public class FooMessage {
public Optional<String> receivedMessage;
public FooMessage(String message) {
this.receivedMessage = Optional.ofNullable(message);
}
}
and then the Main class:
public class Main {
public static FooMessage receiveMessageWithNull(){
return new FooMessage(null);
}
public static FooMessage receiveMessage(String s){
return new FooMessage(s);
}
public static void fooMethod() {
System.out.println("Message == null");
}
public static void fooMethod(String message) {
System.out.println("Message != null");
}
public static void main(String[] args) {
//Calls that return a Message either with content or without
FooMessage message = receiveMessage("foo");
FooMessage messageWithNull = receiveMessageWithNull();
//Resolving which version of the overloaded method to call
if (message.receivedMessage.isPresent()) {
fooMethod(message.receivedMessage.get());
} else {
fooMethod();
}
if (messageWithNull.receivedMessage.isPresent()) {
fooMethod(messageWithNull.receivedMessage.get());
} else {
fooMethod();
}
}
}
My question is if there is a possibility to clean the code up in a way that the method call itself is written to resolve the checks currently done in the if statements. I was thinking about something like:
fooMethod(message.receivedMessage.isPresent() ? message.receivedMessage.get() : ... );
Instead of ... there would be something that told the method to ignore the parameter.
Note: I cannot change fooMethod. I have to resolve which version of fooMethod has to be called in the calling method.
If you need to execute the method only if the Optional value is present, and you do not care for an absent value, you may go with
message.receivedMessage.ifPresent(Main::fooMethod);
I would avoid passing the Optional to a method that then distinguishes whether the value is present, but you can implement a support function that would hide the implementation details
private static void distinguish(String s) {
if (s == null) fooMethod();
else fooMethod(s);
}
and cal it via
distinguish(message.receivedMessage.orElse(null));
This is an acceptable way of using Òptional::orElse.
From the docs:
/**
* Return the value if present, otherwise return {#code other}.
*
* #param other the value to be returned if there is no value present, may
* be null
* #return the value, if present, otherwise {#code other}
*/
public T orElse(T other) {
return value != null ? value : other;
}
I would personally just stick with if (optional.isPresent()) as this is what optionals are intended for, so I wouldn't worry too much.
I am trying to abstract some common checks for an Android library and add Nullability annotations at the same time but I am getting a warning.
Let's say I have an example method in this library:
public int method(#Nullable final String param) {
final int precheckResult = LibPrechecks.checkForMethod(param); // Does check for param not being null
if (LibPrechecks.checksFailed(precheckResult)) {
return precheckResult;
}
// Rest of logic
return internalMethod(param); // IDE is complaining that param cannot be null
}
That then calls another internal method of the library for some processing:
private int internalMethod(#NonNull String param) {
// processing logic
return 0;
}
And here is an example "precheck" class:
public class LibPrechecks {
public static int checkForMethod(#Nullable final String param) {
if (param == null) {
return -1;
}
return 0;
}
public static boolean checksFailed(final int precheckResult) {
return precheckResult < 0;
}
}
I am returning an error code upon a null so I know it's safe and non-null by the time the internal method is called with the param, but the IDE is still unhappy and thinks the param could be null. How would I fix the warning in Android Studio and do this properly?
The IDE doesn’t know what checkForMethod() or checksFailed() do, so you need to either suppress the warning or write some code that the IDE can statically analyze to prove that param is not null.
I think the best thing to do would be to assert that param is not null after the precheck code is done running. Either
assert param != null;
or
if (param == null) throw new AssertionError();
will work.
I want to save a method in an Enum, but Class.getDeclaredMethod is throwing NoSuchMethodException, so how can I handle it?
My Code:
public enum Card {
OPENPRISON(false, Cards.class.getDeclaredMethod("", Player.class));
private boolean isInstant;
private Method method;
private Card(boolean isInstant, Method method){
this.method = method;
this.isInstant = isInstant;
}
public boolean isInstant() {
return isInstant;
}
public void run(Player p){
}
}
and OPENPRISON is the problem
An immediate technical issue is that you're not providing a method name in your call to getDeclaredMethod():
OPENPRISON(false, Cards.class.getDeclaredMethod("", Player.class));
A larger issue is why you need to use reflection at all.
An enum value is a constant. What can you do with reflection that you could not as easily do with a static method? Or with a method outside the enum?
Well your code throws a checked exception, so you could use a method:
OPENPRISON(false, foo());
private static Method foo() {
try {
return Cards.class.getDeclaredMethod("", Player.class);
} catch (NoSuchMethodException e) {
return null;
}
}
Of course, the question remains if you cannot solve your problem without reflection - most likely it is possible.
This is the code of the method that I want to simplify. The method name I call of SerializedExpFamMixture class is exactly the value of "model", my question is how to assign the value of "model" directly as the name of the method instead of using "if" to determine which method I should call. Since by using "if", I need to list all the possible values of "model" and judge which method I should use.
Thank you very much for help. I am new to java.
public static SerializedExpFamMixture RateMtxModel(String model)
{
SerializedExpFamMixture result=new SerializedExpFamMixture();
if(model=="kimura1980()")
result=SerializedExpFamMixture.kimura1980();
if(model=="accordance()")
result=SerializedExpFamMixture.accordance();
if(model=="pair()")
result=SerializedExpFamMixture.pair();
return result;
}
One way you can approach this is to use Reflection:
Method method = myClass.getClass().getMethod("doSomething", null);
method.invoke(myClass, null);
Since you are new to Java, it's time for some general pointers:
In Java, we usually name our methods with camelCase, so the first letter is lower case.
Also, in Java we usually leave the opening curly-bracket on the same line as the code (no newline).
Always use final on your variables. At least your parameters. That way you won't overwrite it, and thus won't have to try to figure out which value it actually has at runtime.
Use curly-brackets! Please!
The result variable is not actually needed.
Use the equals-method to compare Strings.
If you only want one result, use else-if
Fixing these things, your method looks like this:
public static SerializedExpFamMixture rateMtxModel(String model) {
if (model.equals("kimura1980()")) {
return SerializedExpFamMixture.kimura1980();
} else if (model.equals("accordance()")) {
return SerializedExpFamMixture.accordance();
} else if(model.equals("pair()")) {
return SerializedExpFamMixture.pair();
}
return new SerializedExpFamMixture();
}
Next, let's look at what you are actually trying to do here. You want to pass some Strings around, and use them as a basis for creating objects. And now, with the advice given here, you will do this using reflection. This does not sound like a very good idea to me. Say you were to go through with this, and this happened:
rateMtxModel("kinura1980");
Small typo, hard to spot, will give unexpected results. If you were actually calling a method the compiler would let you know that you messed up, now you will get no warning (btw did you see both errors in that method call?). The same if someone were to delete the accordance()-method, the compiler would not alert them that this will break the program.
If it was up to be I would just use the static factory-methods in SerializedExpFamMixture directly, but if you have to do it like this (if the task at hand is using a String input to create an object) I would do something like this:
public enum Something {
KIMURA1980("kimura1980()"),
ACCORDANCE("accordance()"),
PAIR("pair()");
private final String stringValue;
private Something(final String stringValue) {
this.stringValue = stringValue;
}
public static Something fromString(final String string) {
for (final Something something : values()) {
if (something.stringValue.equals(string)) {
return something;
}
}
return null;
}
}
public static SerializedExpFamMixture rateMtxModel(final String model) {
if (model == null) {
throw new IllegalArgumentException("model is null!");
}
final Something something = Something.fromString(model);
if (something == null) {
return new SerializedExpFamMixture();
}
switch(something) {
case KIMURA1980:
return SerializedExpFamMixture.kimura1980();
case ACCORDANCE:
return SerializedExpFamMixture.accordance();
case PAIR:
return SerializedExpFamMixture.pair();
default:
return new SerializedExpFamMixture();
}
}
This way, the one place where you will use the Strings is in the enum, the rest of the code will use the enum constants and thus have the safety of the compiler to rely on.
One could also leave the linking between operation and String to the enum, like this:
interface Operation<T> {
public T run();
}
public enum Something {
KIMURA1980("kimura1980()", new Operation<SerializedExpFamMixture>() {
public SerializedExpFamMixture run() {
return SerializedExpFamMixture.kimura1980();
}
}) ,
ACCORDANCE("accordance()", new Operation<SerializedExpFamMixture>() {
public SerializedExpFamMixture run() {
return SerializedExpFamMixture.accordance();
}
}),
PAIR("pair()", new Operation<SerializedExpFamMixture>() {
public SerializedExpFamMixture run() {
return SerializedExpFamMixture.pair();
}
}),
DEFAULT(null, new Operation<SerializedExpFamMixture>() {
public SerializedExpFamMixture run() {
return new SerializedExpFamMixture();
}
});
private final String stringValue;
private final Operation<SerializedExpFamMixture> operation;
private Something(final String stringValue, final Operation<SerializedExpFamMixture> operation) {
this.stringValue = stringValue;
this.operation = operation;
}
public static Something fromString(final String string) {
if (string != null) {
for (final Something something : values()) {
if (string.equals(something.stringValue)) {
return something;
}
}
}
return DEFAULT;
}
public SerializedExpFamMixture getCorrespondingSerializedExpFamMixture() {
return operation.run();
}
}
With this setup in the enum (I think the Operation-part can be trimmed out with Java8), the method will be as simple as:
public static SerializedExpFamMixture rateMtxModel(String model) {
return Something.fromString(model).getCorrespondingSerializedExpFamMixture();
}
Use reflection, but you need to consider a few things:
Bug alert! Comparing Strings using == doesn't work as expected in java - use .equals() instead. However, the solution below bypasses that problem
For the general case, which includes methods not visible to the invoker, you need to consider accessibility, both in finding the method and invoking it
You don't need the result variable, and even if using your code, don't need to initialize it
Try this:
String methodName = model.replace("(", "").replace(")", "");
try {
// getMethod() returns only public methods, getDeclaredMethod() returns any visibility
Method method = SerializedExpFamMixture.class.getDeclaredMethod(methodName);
// if the method is not guaranteed to be visible (eg public) you need this:
method.setAccessible(true);
return (SerializedExpFamMixture) method.invoke(null); // how to invoke on the class object
} catch (Exception forBrevity) {
return new SerializedExpFamMixture();
}
I have this vector that I am defining as an instance variable and also as an inner class:
private Vector<MATIdentifier> matIds = new Vector<MATIdentifier>(){
#Override
public boolean add(MATIdentifier mi){
if(this.contains(mi)){
return false;
}
super.add(mi);
return true;
}
#Override
public boolean contains(Object o){
if(o instanceof MATIdentifier){
for(MATIdentifier mi: this){
if(mi.getIdValue().equals(((MATIdentifier)o).getIdValue())){
return true;
}
}
}
return false;
}
};
Later on in the program, I want to populate this vector from the database. And it would be better to create a new instance of this Vector class, as opposed to simply removing all the elements and reusing the same object - I suppose I could do that, but I still want to know about cloning the object.
The only way I know how to do this would be to clone() this object. Is this safe? Will it clone the overridden methods add(MATIdentifier) and contains(Object) ?
Maybe I should override clone() also...? Or is the predefined clone() method in Vector sufficient?
Note: I put the #Override annotations in myself, the Java compiler (Eclipse) did not make me do that for some reason.
This question deals with several concepts in Java.
Firstly, I'd like to ask why, if you want to guarantee uniqueness, you aren't using a java.util.Set?
Next, the clone method. Is the clone a shallow copy or a deep copy of the original data structure? If we look at the Vector API documentation from Oracle, it tells us:
Returns a clone of this vector. The copy will contain a reference to a
clone of the internal data array, not a reference to the original
internal data array of this Vector object.
So we can learn from this that, firstly, it also clones the internal data, so this suggests a deep copy. Now, does it also copy the overridden methods? A quick test of this tells me that, yes, it does.
Finally, how to test this? I suggest you use a unit testing framework like junit.
Following is an example of how to use this framework to ensure your assumptions are correct:
package test.good;
import static org.junit.Assert.*;
import java.util.Vector;
import org.junit.Before;
import org.junit.Test;
public class CloneTest {
private Vector<MATIdentifier> matIds;
MATIdentifier id1 = new MATIdentifier("first");
MATIdentifier id2 = new MATIdentifier("second");
MATIdentifier id3 = new MATIdentifier("third");
MATIdentifier idDuplicate = new MATIdentifier("first");
#Before
public void prepare() {
matIds = new Vector<MATIdentifier>() {
#Override
public boolean add(MATIdentifier mi) {
if (this.contains(mi)) {
return false;
}
super.add(mi);
return true;
}
#Override
public boolean contains(Object o) {
if (o instanceof MATIdentifier) {
for (MATIdentifier mi : this) {
if (mi.getIdValue().equals(((MATIdentifier) o).getIdValue())) {
return true;
}
}
}
return false;
}
};
}
private void populateVector(Vector<MATIdentifier> vector) {
vector.add(id1);
vector.add(id2);
vector.add(id3);
}
/**
* Tests that adding new values returns true, and adding duplicates returns
* false, and that the duplicates are not actually added
*/
#Test
public void testDuplicateFails() {
boolean added;
added = matIds.add(id1);
assertTrue(added);
added = matIds.add(id2);
assertTrue(added);
added = matIds.add(idDuplicate);
assertFalse(added);
assertEquals(2, matIds.size());
}
#Test
public void testDeepCopy() {
// Start with by pupulating our customized vector
populateVector(matIds);
assertEquals(3, matIds.size());
// Clone the vector
Vector<MATIdentifier> clone = (Vector<MATIdentifier>) matIds.clone();
assertEquals(3, clone.size());
// remove something from the original
matIds.remove(2);
assertEquals(3, clone.size());
assertEquals(2, matIds.size());
// add something to the original
matIds.add(new MATIdentifier("New Value"));
assertEquals(3, clone.size());
assertEquals(3, matIds.size());
// add a duplicate to the clone, to ensure that the overridden behavior
// is present in the clone
boolean added = clone.add(id1);
assertFalse(added);
}
}
class MATIdentifier {
private String idValue;
public MATIdentifier(String idValue) {
this.idValue = idValue;
}
public String getIdValue() {
return idValue;
}
public void setIdValue(String idValue) {
this.idValue = idValue;
}
}
PS, it's probably better practice to either override the equals operation on MATIdentifier or to create a MATIdentifier Comparator than to create a custom contains and add impl for your Vector. I'd really suggest you use a java.util.Set.
Also, creating anonymous inner types like this with what I assume is important functionality is not a good practice, as it makes your code more difficult to test. If you insist on continuing with a specialized Vector implementation, you should move it into a class.