In Java what is the best practice of initializing the private string members
class A {
private String mem = ??//
private int num;
A (int a) {
this.num = a;
}
A (int a, String s) {
this.num = a;
this.mem = s; //What if s is null (Is this a good practice)
}
}
Totally depends on what you are doing...
Ask yourself these questions (whenever you make any variable)
will the value ever change?
what are the allowed valued?
In this case if "mem" and "num" will never change then mark them as final (you can always take away the final later if you find you will have to change them).
Also in this case can "mem" ever be null? Can num ever be < 0?
Here is an example of the changes I might make:
class A
{
private final String mem;
private int num;
A (final int a)
{
this(a, null);
}
A (final int a,
final String s)
{
if(a < 0)
{
throw new IllegalAgumentException("a cannot be < 0, was: " + a);
}
num = a;
mem = s;
}
}
In short there is no best practice.
Depends on your model. Some strings may need to be nullable and others (mandatory) should always contain a value. Sometimes more than just an empty string.
I wouldn't blindly allocate the empty string to everything.
Leave it blank: private String mem;
With regard to "What if s is null", one should make it a point to construct all objects in a valid state. But what is "valid" depends completely on your application. When the rest of your program references mem and finds it to be null, what will happen? Would it be better to have it be an empty string or some other default value? It varies depending on the circumstances.
There is a trick with this (and most variables, actually).
If you NEVER initialize the variable, you are actually giving the compiler more information.
In some cases you have to, but this case is really interesting:
String s;
if(a==5)
s="It was Five";
if(a==6)
s="It was Six";
System.out.print(s);
This is very bad code, but the neat thing is, Java will catch it and tell you "Hey, there is a good chance that you'll hit that print with a null".
If you had started with either of these two lines:
String s=null;
String s="";
The compiler couldn't have helped you with that mistake. (It's not likely that you meant to print "", is it?)
The correct fix when you see this "variable might not have been initialized" message is NOT to initialize the string to null or "". It's to actually be sure s is set to a valid value in every possible path:
if(a==5)
s="It was Five";
else if(a==6)
s="It was Six";
else
s="It was something else, who knows?";
This will compile fine, even without initializing s. This works on complex if/else, looping and exception cases, so don't just assume it will only catch trivial cases like this!
So "Best Practice" is to NEVER initialize variables to "", 0 or null. Don't initialize them unless it really makes sense and you are using the value you set it to in some way.
Once you get the error in my example, instead of the else you might just initialize s to "It was something else, who knows?" instead of adding the else--that would be perfectly valid; but by not initializing it to null or "" as a matter of habit, at least it was able to remind you that you had to do so.
It depends on the usage of that attribute.
Is a null a valid input in your program?
If it's not, then you should validate it and throw a Npe.
A ( int a, String s ) {
if( s == null ) {
throw new NullPointerException("The value of s cannot be null");
}
....
}
If it is a valid value, then there won't be a problem.
It is a good practice though that you assign the value only in one place, so you don't get surprises if you validate in the constructor, but later a setter change the value.
If the String is never supposed to be null, then the constructor that sets it from a parameter should throw an Exception if the parameter is null, and the other constructor should set it to a useful default value.
If the String is never supposed to be null, you can declare it final, and this way the compiler makes sure that all constructors assign a value to it.
class A {
private final String mem;
private int num;
A (int a) {
this.num = a; // <= compile error, mem must be assigned
}
A (int a, String s) {
this.num = a;
this.mem = s; // <= you need to null-check yourself
}
}
It is still up to the constructors to make sure that they don't just assign null.
Maybe the future will bring a #NotNull annotation...
You should define a contract and then code to it. If you allow the member to be null, then initialize it to null. If not, usually initializing to empty string "" is a good idea. But again, it depends on your data model, sometimes empty string is invalid too.
In all cases, your constructor should throw NullPointerException or IllegalArgumentException if an invalid string is passed in.
Related
There is a method:
private String myMethod(String gender)
{
String newString = "";
if(gender.equals("a"))
newString = internal.getValue();
else
newString = external.getValue();
return newString;
}
I refactored everything, but with one small change:
String newString; instead of: String newString = "";
Does this refactor improve the code? I know that String is null when we don't initialize it, but in this example it always will have value a from if or else. Does this refactor change anything?
To answer the direct question: there's no need to assign a value initially here; all branches of the code's execution will pan out to giving newString a value. Thus you don't need to initialize it at all. Otherwise, I would initialize to whatever you would want as a "default" value.
Instead of two returns or a branching statement to assign a variable, I would just return with a ternary:
private String myMethod(String gender) {
return gender.equals("a")
? internal.getValue()
: external.getValue();
}
Is it better to initialize String or to leave it as null?
Your premise is flawed: not initializing the String doesn't mean its value is null.
You are not allowed to use a local variable before it has been assigned, in order to avoid you accidentally using a value you didn't intend. As such, the value isn't "null", it's undefined (*).
This is called definite assignment checking, and is there to prevent certain types of bug. If you give the variable a value you don't need to give it, you disable this check, and so are open to the bugs the compiler was trying to protect you from.
For example, if the code looked like this:
private String myMethod(String gender)
{
String newString = "";
if(gender.equals("a"))
newString = internal.getValue();
else if (gender.equals("b");
newString = external.getValue();
// Oops! meant to check if gender.equals("c")
return newString;
}
you might have a bug, because there is a missing case that you haven't checked.
If you had explicitly assigned null to the variable, you would have much the same issue; but now your method would return null, and so possibly cause an NPE in the calling code.
If you had omitted the = "", the compiler would stop you using newString in the return.
(Assigning and reassigning the variable also means the variable would not be effectively final, so you would be unable to use it inside a lambda or anonymous class).
(*) This only applies to local variables, and final member/static variables. Class members do not have to be definitely assigned before use if they are not final, which is a rich seam for bugs, and a good reason to make class members final wherever possible. And, technically, final members are initialized to their type's default value first, so you can actually read them as null before they are initialized.
It's best to only initialize a String (or anything else) if there is a scenario in which the initial value is used.
In your case you have assigned newString to a string literal that serves no purpose but to confuse the reader.
It should be evident that the performance and functionality will not change in any relavent way.
My take on the shortest form without the terniary operator (which I think decreases readability) :
private String myMethod(String gender)
{
if(gender.equals("a"))
return internal.getValue();
return external.getValue();
}
I would probably have a full if {...} else {...} construct like the other answers in my own code.
Also not all debuggers can easily show what is being returned from a method as part of the normal flow, so it may be easier if the return value is captured in a variable and THEN returned (where the breakpoint can be put on the return statement)
You can make this string final and keep unassigned to be sure that all if branches assigns the value:
final String result;
if (condition1) {
result = "one";
} else if (condition2) {
result = "two";
} else {
result = "other";
}
return result;
With this approach compiler will check that result variable was assigned once in each branch. It may be helpful if you add one more condition branch, or if you try to overwrite variable by mistake - compiler will fail and show the error.
In your case (if else condition) there no need to initialize the String, you can simple put it as String newString; and that would be ok because either way, at the end it will have a different value.
private String myMethod(String gender)
{
String newString;
if(gender.equals("a"))
newString = internal.getValue();
else
newString = external.getValue();
// Missing return statement.
}
Also, I see that you have a function that returns a string. Assuming that the newString variable is what you will be returning, instead of creating a string variable you can simple return the string in the condition:
private String myMethod(String gender)
{
if(gender.equals("a"))
return internal.getValue();
else
return external.getValue();
}
My colleges are right, this can be done with the tenary operator.
In addition I thinks its very important to prevent NullPoiterExeptions as often as possible.
What if gender would be null? NullPointerException
I would switch "a" and gender like this:
private String myMethod(String gender) {
return "a".equals(gender)
? internal.getValue()
: external.getValue();
}
According to Java doc:
Default Values
It's not always necessary to assign a value when a field is declared. Fields that are declared but not initialized will be set to a reasonable default by the compiler. Generally speaking, this default will be zero or null, depending on the data type. Relying on such default values, however, is generally considered bad programming style.
Local variables are slightly different; the compiler never assigns a default value to an uninitialized local variable. If you cannot initialize your local variable where it is declared, make sure to assign it a value before you attempt to use it. Accessing an uninitialized local variable will result in a compile-time error.
New to Java, sorry if this is a stupid question. I'd like to assign new values to a couple of variables from inside a while loop, but that's not working. I'm getting an error "The local variable newString may not have been initialized" when trying to compile. Here's an example:
public class Test {
public static String example() {
String first;
String second;
String newString;
int start = 1;
while (start<5) {
if (start<4) {
first = "hello";
second = "world";
newString = first + second;
}
start += 1;
}
return newString;
}
public static void main(String[] args) {
System.out.println(example());
}
}
When you are returning a variable as a result from a method, the compiler needs to be sure that a value would be assigned to that variable (in your case newString).
Although it is pretty clear for you that the condition start < 4 will be true at some points, the compiler is not intelligent enough to figure that out, which means you have to return only variables, which has values for sure.
Depending on the purpose of your method, you have the following opportunities:
String newString = "";
In this case you are sure that your method will never return null, which could be tricky in some cases for finding errors.
Another opportunity is
String newString = null;
if you want to allow your method to return null values.
As it is obvious in this case that you will eventually enter the if-block and assign a value to the variable newString in other cases it won't be that obvious, so you need to determine whether to allow your method return null values or not.
You are getting this error because the compiler does not know if newString will ever be initialized before it gets returned.
Although you know that both start<5 and start<4 are true and will, thus, execute, the compiler doesn't perform these types of calculations during compilation. Hence, for all it knows, those statements will never execute, and thus newString may get returned before it is initialized.
Hence, you should initialize it (e.g. to null) when you declare it to avoid this error.
There is a rule in Java that all local variables must be initialized before they are first read. You are using newString as a return value, which is a read operation. Although you are assigning a value to newString, it is done in conditional situation (start<5 && start<4). At the compile time, the compiler does not know what will be the result of running the code and it conservatively complains about this situation.The simple solution will be initializing the string:
String newString = "";
What is the best approach to validate the arguments for null while calling a method?
1) before making the method call
private void myMethod(String param1, String param2){
String a = param2;
if(StringUtils.isNotBlank(a)){
validate(a);
}
}
private void validate(String a) {
int temp = Integer.parseInt(a);
if(a > 4){
addError()
}
}
2) inside the method once you receive the arguments
private void myMethod(String param1, String param2){
String a = param2;
validate(a);
}
private void validate(String a) {
if(StringUtils.isNotBlank(a)){
int temp = Integer.parseInt(a);
if(a > 4){
addError()
}
}
}
OR Both
IMO, StringUtils.isNotBlank(a) is some form of validation only, so it should be in validate() method. And if that has to be checked every time you call validate() method, then certainly it will make more sense to move it there.
From the two approaches you give, the second is better.
Reason: DRY principle (Don't Repeat Yourself aka avoid code duplication).
The code in the first snipped duplicates (or triplicates, etc) the "check for blank" part of the code for every place validate() is called.
Also the responsibility of the consistency, the "not blank" invariant (a domain/business rule), belongs (is inherent) to the validate() method, so it should have the responsibility for taking care of it.
In practical terms: Consider the possibility of a change to this domain rule, if one needed to add some new check to it, in what case you'd have to change less (thus less error-prone)? Where the developer that'll do the change would expect to find such rule? In the validate() or scattered through the whole code base?
If that error validation is useful everytime you call some method, it obviously should be done inside the method, or else you would have to do it everytime before calling that method. Just remember to comment the code, so you remember that later.
Conceptually the validate() method should capable to identify that the passing parameter is null or not. So in your given scenario the approach 2 should be preferable.
Would be inside the method throwing a java.lang.IllegalArgumentException.
Like:
private void validate(String a) {
if(StringUtils.isNotBlank(a)){
int temp = Integer.parseInt(a);
if(a > 4){
addError()
}
}
else{
throw new IllegalArgumentException("argument must not be null or blank");
}
}
What is the best approach to validate the arguments
IMO, your second approach is better one
because it is not a task for which you have to provide a separate method, it is just a parameter validation which is part of same logic which you are going to implement in your method. and another thing to be considered is second approach will form higher redability of your code.
OR Both
NEVER, Choose one as per your coding practice and stick to it.
Other considerations for validation :
Check parameters annotated with #Nonnull for null?
You can use assertion for Private arguments.
If the following code is possible:
Integer a = null;
int b = a;
Does it mean that a function returning a possible null value for an integer is a bad practice?
Edit 1:
There are several different opinions in these answers. I am not enough confident to choose one or another.
That code will give a NullPointerException when you run it. It's basically equivalent to:
Integer a = null;
int b = a.intValue();
... which makes it clearer that it will indeed fail.
You're not really assigning a null value to an int - you're trying and failing.
It's fine to use null as a value for an Integer; indeed often Integer is used instead of int precisely as a "nullable equivalent`.
It is not possible. You will get NullPointerException
That will throw a NullPointerException.
The reason for this is that you're relying on auto-unboxing of the Integer value to an int primitive type. Java does this by internally calling .intValue() on the Object, which is null.
As to either it's a good practice or not... I would advise against doing so, unless the code is only used by you and you're extremely well behaved, making sure that you only assign the return value of such method to Integer values, not int.
If your code ends up in a lib used by others, it's not safe, and I would rather explicitly throw an Exception, well documented, and allow for defensive coding on the caller's part.
Funny thing with Java tenerary operator ?: (using 8u151 on OSX)
If you do
Integer x = map == null ? 0 : map.get ( key );
which seems fine and compact and all, then you get an npe!!! if
map.get ( key )
is a null. So I had to split that and it worked fine.
Of course you cannot assign null to an int. But returning a null in some situations makes sense. Null can mean that the value is not set. A typical example is a DB column.
The code is possible, but throws a NullPointerException at runtime, because of unboxing. Regarding
Does it mean that a function returning a possible null value for an
integer is a bad practice?
yes, it is. It's useless and dangerous (as you can see) to return an Integer when a int is enough, because objects can be null, while primitives can't. Integer should be used only when needed, like in a parameterized type - List<Integer>
From Java 8, we can use Optional:
// example: if an Integer object is null, an int value could receive 0, for example:
Integer value = getSomeInteger (...); // (0, null, or some other numeric value)
int inteiro = Optional.ofNullable(value).orElse(0);
That would work indeed.
Integer a = null;
Integer b = a;
But I would rather use a int value out of range (-1 if your numbers are all positive) to return in case of an error.
It's a bout Java auto-boxing.
Integer a = null;
int b = a;
this code assign a to b,actually the compiler will do this:int b=a.intValue(), so this line will throw NullPointerException;
the code :
Integer a = 1;
will actually do this: Integer a = Integer.valueOf(1);
You can use javap to see the compiled virtual machine instructions。
You can write simple test:
public class Test {
public static void main(String[] args){
Integer a = null;
int b = a;
System.out.println(b);
}
}
And the output is a NullPointerException on int b = a;
Exception in thread "main" java.lang.NullPointerException
at Test.main(Test.java:11)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
With a third party API I observed the following.
Instead of using,
public static string getString(){
return "Hello World";
}
it uses something like
public static void getString(String output){
}
and I am getting the "output" string assigned.
I am curious about the reason of implementing such functionality. What are the advantages of using such output parameters?
Something isn't right in your example.
class Foo {
public static void main(String[] args) {
String x = "foo";
getString(x);
System.out.println(x);
}
public static void getString(String output){
output = "Hello World"
}
}
In the above program, the string "foo" will be output, not "Hello World".
Some types are mutable, in which case you can modify an object passed into a function. For immutable types (such as String), you would have to build some sort of wrapper class that you can pass around instead:
class Holder<T> {
public Holder(T value) {
this.value = value;
}
public T value;
}
Then you can instead pass around the holder:
public static void main(String[] args) {
String x = "foo";
Holder<String> h = new Holder(x);
getString(h);
System.out.println(h.value);
}
public static void getString(Holder<String> output){
output.value = "Hello World"
}
That example is wrong, Java does not have output parameters.
One thing you could do to emulate this behaviour is:
public void doSomething(String[] output) {
output[0] = "Hello World!";
}
But IMHO this sucks on multiple levels. :)
If you want a method to return something, make it return it. If you need to return multiple objects, create a container class to put these objects into and return that.
I disagree with Jasper: "In my opinion, this is a really ugly and bad way to return more than one result".
In .NET there is a interesting construct that utilize the output parameters:
bool IDictionary.TryGet(key, out value);
I find it very usefull and elegant. And it is the most convenient way to aks if an item is in collection and return it at the same time. With it you may write:
object obj;
if (myList.TryGet(theKey, out obj))
{
... work with the obj;
}
I constantly scold my developers if I see old-style code like:
if (myList.Contains(theKey))
{
obj = myList.Get(theKey);
}
You see, it cuts the performance in half. In Java there is no way to differentiate null value of an existing item from non-existance of an item in a Map in one call. Sometimes this is necessary.
This functionality has one big disadvantage - it doesn't work. Function parameters are local to function and assigning to them doesn't have any impact outside the function.
On the other hand
void getString(StringBuilder builder) {
builder.delete(0, builder.length());
builder.append("hello world");
}
will work, but I see no advantages of doing this (except when you need to return more than one value).
Sometimes this mechanism can avoid creation of a new object.
Example:
If an appropriate object exists anyhow, it is faster to pass it to the method and get some field changed.
This is more efficient than creating a new object inside the called method, and returning and assigning its reference (producing garbage that needs to be collected sometime).
String are immutable, you cannot use Java's pseudo output parameters with immutable objects.
Also, the scope of output is limited to the getString method. If you change the output variable, the caller won't see a thing.
What you can do, however, is change the state of the parameter. Consider the following example:
void handle(Request r) {
doStuff(r.getContent());
r.changeState("foobar");
r.setHandled();
}
If you have a manager calling multiple handles with a single Request, you can change the state of the Request to allow further processing (by other handlers) on a modified content. The manager could also decide to stop processing.
Advantages:
You don't need to return a special object containing the new content and whether the processing should stop. That object would only be used once and creating the object waste memory and processing power.
You don't have to create another Request object and let the garbage collector get rid of the now obsolete old reference.
In some cases, you can't create a new object. For example, because that object was created using a factory, and you don't have access to it, or because the object had listeners and you don't know how to tell the objects that were listening to the old Request that they should instead listen to the new Request.
Actually, it is impossible to have out parameters in java but you can make a work around making the method take on a de-reference for the immutable String and primitives by either writing a generic class where the immutable is the generic with the value and setter and getter or by using an array where element 0 (1 in length) is the value provided it is instantiate first because there are situations where you need to return more than one value where having to write a class just to return them where the class is only used there is just a waste of text and not really re-usable.
Now being a C/C++ and also .Net (mono or MS), it urges me that java does not support at least a de-reference for primitives; so, I resort to the array instead.
Here is an example. Let's say you need to create a function (method) to check whether the index is valid in the array but you also want to return the remainding length after the index is validated. Let's call it in c as 'bool validate_index(int index, int arr_len, int&rem)'. A way to do this in java would be 'Boolean validate_index(int index, int arr_len, int[] rem1)'. rem1 just means the array hold 1 element.
public static Boolean validate_index(int index, int arr_len, int[] rem1)
{
if (index < 0 || arr_len <= 0) return false;
Boolean retVal = (index >= 0 && index < arr_len);
if (retVal && rem1 != null) rem1[0] = (arr_len - (index + 1));
return retVal;
}
Now if we use this we can get both the Boolean return and the remainder.
public static void main(String[] args)
{
int[] ints = int[]{1, 2, 3, 4, 5, 6};
int[] aRem = int[]{-1};
//because we can only scapegoat the de-ref we need to instantiate it first.
Boolean result = validate_index(3, ints.length, aRem);
System.out.println("Validation = " + result.toString());
System.out.println("Remainding elements equals " + aRem[0].toString());
}
puts: Validation = True
puts: Remainding elements equals 2
Array elements always either point to the object on the stack or the address of the object on the heap. So using it as a de-references is absolutely possible even for arrays by making it a double array instantiating it as myArrayPointer = new Class[1][] then passing it in because sometimes you don't know what the length of the array will until the call going through an algorithm like 'Boolean tryToGetArray(SomeObject o, T[][] ppArray)' which would be the same as in c/c++ as 'template bool tryToGetArray (SomeObject* p, T** ppArray)' or C# 'bool tryToGetArray(SomeObject o, ref T[] array)'.
It works and it works well as long as the [][] or [] is instantiate in memory first with at least one element.
in my opinion, this is useful when you have more than one result in a function.