Constructor with Optional<String> - java

I have written the following code:
void Test(A a) {
B b = new B(a.getName());
}
So, the constructor of B expects a String. It looks like the following:
protected B (String name) {
super(name, KIND);
this.name = name;
}
But a.getName() gives me a name with Optional<String> as return value and I do not want to change that. Therefore, I try to change the parameter of the constructor B (I replace String name with Optional<String>), but then Eclipse underlines super(name, KIND) and this.name = name with red and Eclipse recommends to change the parameter of the constructor again to String name.
How can I solve it?
best regards,

An Optional<String> might contain a String, so you need to check for that (and generally speaking, handle the case where it is absent). So your Test() method might look like this:
void Test(A a){
// Consider adding a a.getName().isPresent() check and handling the false
// case if you need to. Otherwise you'll get an IllegalStateException.
B b = new B (a.getName().get());
}
In general, the better practice is to leave your constructor parameter as a String, and then convert it into a n Optional<String> when you store it.
The alternative, if you really want users to pass in Optionals, which does sometimes make sense, is to fix the super() constructor to also take an Optional<String>. If you can't do that, you need to similarly call .get() and pass the resulting String into super(); again handling the absent case as needed.

You could make another constructor that takes aan Optional.

Related

Dynamic value in Custom Annotation

Is there a way I could pass in a dynamic value into a Custom Annotation?
For example as follows:
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface CustomAnnot {
String[] requestKeys();
}
When annotating, I want to pass in the value of the argument dynamically.
#CustomAnnot(requestKeys = {"id"}) // or maybe "#id"
public Object get(String id) {}
To note the above won't just work. Need some form of parsing for this to work.
How can I go about doing this? Trying to find online references and but unable to find anything to aid in this implementation.
#Cacheable in Spring is able to do this thus clearly this is possible. Tried to have a look over the implementation for #Cacheable and to be honest got lost. It's massive and a struggle to debug. Could I get some advice on this implementation or if anyone familiar point to the part where cacheable implements this? Thanks.
EDIT:
I need a way to get values from arguments in a method.
Example.
// maybe in this method I only want String b and c
String method1(String a, String b, String c){
return null;
}
// maybe here I want String a and c
String method2(int d, String a, String b, String c){
return null;
}
// just 1 argument here so only need String a
String method3(String a){
return null;
}
I am looking for a single way to get the values of what I need in 1 way.
I want to write this functionality once and be done with it, not have to come back again for a different method signature.
Thus I was going for a custom annotation which gives me flexibility to decide what values I want so I can pass in an array .

Using Varargs, can I assign values to variables based on the variable name?

I am trying to pass a variable number of arguments into a constructor, because not all of the values will always be required, and empty values are okay. Can I make it such that I can pass the variables in, in any order, and have them assign to their corresponding variables in the class correctly?
Few things to note in my case is that the variables in the class are Serialized; the values are either a String, an Integer, a boolean, or a Date; and the values passed into the constructor will always match their corresponding class values (If the value in the class is an Integer, an Integer will always be passed in for that value, not a String.parseInt(), for example)
Class Foo {
#SerializedName("id")
private Integer id;
#SerializeName("name")
private String name;
#SerializedName("isFoo")
private Date isFoo;
public Foo (Object... args){
}
}
In the constructor I want to be able to ask if whatever object name matches a variable in the class, to assign it to that variable. So if one of the Object's passed is an Integer named id, is there a way to match it to id? It should be able to be matched in a few cases:
Foo foo = new Foo(id, name) //In this case, the bool would be null
Foo foo2 = new Foo(name, id, isFoo) //Here the Integer is second, but should still be able to be passed in correctly
I think this can be solved via Reflection but I am not sure how. Any help would be amazing.
I answer your actual question below, but answering the underlying desire of the question, you're probably looking for the Builder pattern:
Foo foo = new Foo.Builder().id(id).name(name).build();
Foo foo = new Foo.Builder().name(name).id(id).isFoo(isFoo).build();
It's one of the original Gang of Four patterns.
(In the above I made Builder a nested class within Foo, as the builder class and the thing it builds tend to be intimately related. But that's not necessary, it's just one way it's done.)
...can I assign values to variables based on the variable name?
No. The variables are not passed to your method. The value contained in the variables is read from them, and that value is passed to your method. By the time it gets to your method, there is no connection whatsoever back to the variable the value came from (if, in fact, it came from a variable).
In your specific example, since each of them has a distinct type, you could check each of the entries in args to see what its type is and work from that, but it would be fairly odd and I wouldn't recommend it.
Emphasizing that I wouldn't recommend it, that would look like:
for (Object arg : args) {
if (arg instanceof Integer) {
this.id = (Integer)arg;
} else if (arg instanceof String) {
this.name = (String)arg;
} else if (arg instanceof Date) {
this.isFoo = (Date)arg;
}
}
But again, I wouldn't recommend it, and if I came across it in a code review I'd want a really, really good justification for it. :-)

Java String predefine

I'm sure this question has allready been answered somewhere, but I' ve searched for half an hour now and I'm running out of keywords, because I have absolutly no idea how to do this.
I have a constructor for a class like this
public MyClass (String name)
{}
what I want is to define Strings so that only those Strings can be entered.
I assume it has something to do with static final strings, but there is quite a lot to be found to those and I dont know how to narrow down the search. Please tell me how that thing I want to do is called, so that I can search for it.
Edit:
Example to what I want:
I want to somehow define a number of Strings. (Or do somethig else that has the same effect, as I said I dont know how to do it)
String one = "ExampleOne";
String two = "ExampleTwo";
so that when I call the constuctor
MyClass myClass = new MyClass("somethingElse");
the constructor wont take it. Or even better eclipse allready showing my what options I have like it does whit "Color. "
Yes you have right you can not override String class because it is final so simply you can create your own StringWrapper class that wraps string.
public class StringWrapper{
private String content;
public StringWrapper(String c){
content = c;
}
//all your methods and fields there, for example delegated methods
public String toString(){
return content.toString();
}
}
But Enum could be also used in your case then you define your Enum values
public enum Color {
WHITE, BLACK, RED, YELLOW, BLUE; //; is required here.
#Override public String toString() {
//only capitalize the first letter
String s = super.toString();
return s.substring(0, 1) + s.substring(1).toLowerCase();
}
}
public myClass (Color color)
{}
There are two ways you can acheive this, either use a enum as constructor parameter. The enum itself contains only the allowed values, which is what I would do, keep everythign nice an oop and you can add logic to enums at a later date.
Or alternatively you can just check if the constuctor paramters value is valid, by performing a comparison and throwing an exception if not in allowed values. Have a predfined list and then, myList.contains(myString) - throw exception if false.
What I want is to define String so that only those Strings can be entered
I think that what you are after are Enums.
Enums will allow you to define a range of values which you can then use. In the example I have linked, the developer can restrict the type of input that he/she will receive to the days of the week.
You can check it in constructor's body at runtime, or if you want to compile-time checks, then you can use enum type argument (enum is a predefined set of constants).
From what I understand it seems like you want to limit what the String can be.
You would do this by putting conditional statements inside the constructor to weed out any Strings you don't want to be entered that would either notify the user that it is an invalid string or throw an exception, and the remainder of the constructor would only be executed in an else statement once it has passed all the tests making sure it is a valid String

Set custom variables from method

I have some String variables:
private String cur, last, avg, vol, shop;
I have method which accept String and gives me some result:
public void SomeMethod(String somestring)
{
//Here some action with `string`
System.out.print(result)
}
So i want to put result into one of String variables, but this variable must be named as value of somestring in my method. Some method which compare somestring with existent variables names. Is such a thing even possible?
You're talking about variable variable name. They're a native feature in PHP, but not in Java, however you can achieve similar functionality using a HashMap, or using Reflection. I'm going to show you the HashMap option, because frankly Reflection is the work of Satan.
Example
Now the way to implement this is like this:
public void someMethod(String name, String value)
{
values.put(name, value);
}
And you can retrieve them with
public void getValue(String name)
{
return values.get(name);
}
I won't write the code for you, because it's a simple transformation to get this to work in your use case.
A hint because I'm feeling nice
You can replace all of your String variables with a Map implementation. Then simply add the values to the Map, as and when the need arises.

Java "this" in constructors

Well, this is a very basic question, I've never coded in java, but I'm writing a class for a friend... Having something like:
class myClass{
private string name;
public string getName() {
return this.name;
}
public void setName (int newValue) {
this.name = newValue;
}
private int number;
public int getNumber() {
return this.number;
}
public void setNumber (int newValue) {
this.number = newValue;
}
}
The way I was thinking of building the constructor was:
public myClass (string name, int numbers) {
this.name = name;
this.number = number;
}
My questions:
I'm using the same identifiers for the properties as for the parameters. Does "this." avoid any trouble here?
Is it better to use the set methods and, if so, should i use "this."?
Thank you very much
Yes, it avoids the name clash. In the constructor's context, the name name refers to the parameter, and the name this.name refers to the instance field.
Depends on what you mean by "better." Personally, I would make the name and number fields final, so the class is immutable. In my experience, it's better to start from an immutable class definition, and only move towards something mutable if there is a legitimate need to do so.
Yes, this differentiates between an instance variable and a method parameter variable of the same name.
There's always debate on whether constructor or setter initialization is better. If you're only going to set the name and number when you first create the object, and won't need to update those variables later, just using the constructor and leaving out the setters is probably better. And yes, in the setter, you'd need to use this if your parameter has the same name as the field you want to set.
There's no problem having the parameter using the same name as the field; the this. explicitly disambiguates and the program will behave as intended.
Depending on your program it may or may not be advantageous to use setters instead of directly writing fields. If you write the values directly in the constructor, then you bypass any runtime checks that you might have in your setters, which could potentially cause your object to hold data it normally can't. On the other hand, if your setter tries to do something with the old value, then you probably don't want to call the setter because, in the constructor, there might not be a meaningful old value. I'd say it's not clearly better or worse to set the fields in the constructor than to use setters, so long as you're careful to avoid breaking the class invariants.
Yes. Using the this keyword avoids issues.
If there are logic in the get/set methods, then you should use them instead. Otherwise, setting the values in the constructor is valid.
1) When the object scope property is the same as the argument name you must use this to differentiate between them. When there is a name clash the local var or argument will take precedence over the property.
For this reason, I don't like to ever have the exact same name for each as it can easily lead to bugs.
2) I also would use the setters from within the constructor, because if there ever needs to be a validation or some other operation done on the argument at time of setting you'll only have to make the change in one place. Otherwise it is duplication and violates the DRY (Don't Repeat Yourself) principle.
I would do:
public myClass (string name, int number) {
setName( name );
setNumber( number );
}
Yes, this. avoids problems. Some people recommend that way, such as Rogue Wave in their book The Elements of Java Style.
Other common ways of dealing with this are:
name members with a "m" or "m_" prefix
private string m_name;
private int m_number;
public myClass(string name, int number) {
m_name = name;
m_number = number;
}
call the parameters a different name, usually a single letter or abbreviated version of the member name
private string name;
private int number;
public myClass(string nam, int num) {
name = nam;
number = num;
}
But I prefer the way you are using now with this.

Categories

Resources