I am new to Java and I'd like to figure out why some code is written in one way instead of another. When you construct an object in Java, the syntax is something like
class variable = new class(parameters);
or
class variable;
variable = new class(parameters);
I wonder why the class name has to be invoked twice. As documented on Wikipedia, Python (which I don't know either) follows what according to me is a more intuitive approach, i.e.
variable = class(parameters)
Is it because Java can handle other possibilities?, e.g.
class1 variable = ... class2(parameters)
Thanks in advance.
Because the left hand side can be a reference type and the right hand side it can be any assignable object type.
This assigns the reference variable variable of type class1 an object of class1.
class1 variable = new class1(parameters);
This assigns the reference variable variable of type class1 an object of subclass1, where subclass1 can be a subclass of class1 or an implementation of class1 interface.
class1 variable = new subclass1(parameters);
Python uses Dynamic Typing (Duck Typing) and hence you need not declare a variable.Dynamic typed languages are those in which variable type checking is done at run-time.
Static typed programming languages are those in which variables need not be defined before they’re used. This implies that static typing has to do with the explicit declaration (or initialization) of variables before they’re employed. Java is an example of a static typed language. Statically typed languages that lack type inference (such as C and Java) require that programmers declare the types they intend a method or function to use. This can serve as additional documentation for the program, which the compiler will not permit the programmer to ignore or permit to drift out of synchronization.Static typed languages are those in which variable type checking is done at compile-time.
Python (which I don't know either) follows what according to me is a more intuitive approach
The concern with dynamic typing, like this is :
variable = class(parameters);
In future if by mistake you misspelled the variable name variable with varaible , it would not be caught at compile time , but you can get erroneous output or exception at runtime. With static typing , Java detects such flaws at compile time itself.
Because they mean different things - and don't need to be the same.
The class descriptor on the left defines the type of the variable. This constrains what can be assigned to that variable, and also provides some guarantees to callers about what the objects there can do.
The class name when it appears on the right is actually the "method name" of a constructor. You're calling a method which creates a new object. The object you create can be anything, so long as it's assignable to the type of the variable.
So for example, you can do this:
Object foo = new String("bar");
or this:
Collection x = new ArrayList();
(though in practice you'd probably want to use generic parameters on that last one - I've left them out here so as not to confuse the question of classes.)
Java is a static typed programming language. However, Python is a dynamic typed programming language.
Wikipedia has very good explanation here.
Class name has to be invoked twice because you have to specify the type of the instance.
You can also do things like this when creating new instance:
public class Test extends Test1 {}
...
Test1 test = new Test(parameters);
Doing things like this will determine which class' variables and methods you can actually access while maintaining stuffs such as class fields.
SomeClass variable;
variable = new SomeClass(params);
The first line declares a variable and states that it is of type SomeClass. At this point the variable is empty and doesn't reference anything.
The second line creates a new object of type SomeClass and stores a reference to it in variable.
Writing both things in one line like this:
SomeClass variable = new SomeClass(params);
can be done to make things shorter. But at the end there is always a variable declaration and an object construction. Variables must always be of some type, you can't declare a variable without type (Java is strongly typed).
The left hand side (reference definition type) is a reference to an object or instance that can be the type of that class or any subclass of that reference type. Also, in accord with the following reference Python is a dynamic type programming language where every variable name (unless it's null) is bound to only an object. Java, on the other hand, is a statically-typed programming language.
Related
I know what is going on inside of my code, and how to fix an error. However, I do not understand why things happen the way they do. Specifically, why my method returns interface List instead of ArrayList interface implementation?
What confuses me the most is after implementing moons as ArrayList, it still returns the interface.
Thanks in advance!
private static ArrayList<HeavenlyBody> makingSetOfMoons(){
List<HeavenlyBody> moons = new ArrayList<>();
for(HeavenlyBody planet : Main.planets){
moons.addAll(planet.getSatellites());
}
return moons;
}
Error output:
Incompatible types. Found: 'java.util.List<com.practice.HeavenlyBody>', required: 'java.util.ArrayList<com.practice.HeavenlyBody>'
Let's look at your method declaration:
private static ArrayList<HeavenlyBody> makingSetOfMoons(){
Java expects the method to return an ArrayList<HeavenlyBody>
But you return the moons variable which is declared:
List<HeavenlyBody> moons = ....
It doesn't matter what type of List subtype that you assign to the variable -- Java sees the variable as a List<HeavenlyBody>, pure and simple. Even if you assign an ArrayList<HeavenlyBody> to this variable, the Java compiler cannot use this to do an automatic implicit cast for you, because you could later in the method change the object that the variable refers to, now or later, and this could cause problems. As Jon Skeet states here:
The compiler uses the declared type of the variable to know how it can be used... it's as simple as that.
One solution is to change the moons variable to:
ArrayList<HeavenlyBody> moons = ...
This would work but would be wrong since it is almost always better to "code to the interface" (see: What does it mean to “program to an interface”?). Better to change the return type expected by the method in its declaration:
private static List<HeavenlyBody> makingSetOfMoons() {
This all gets down to the difference between a reference variable and a reference (or object), specifically the type of each. It is a fine distinction but an important one.
The variable and its type:
List<HeavenlyBody> moons
This variable is a reference variable that refers to an object, as opposed to a primitive variable that refers to a primitive type.
Currently you assign this reference to the variable:
new ArrayList<>();
and so the type of the variable is List<HeavenlyBody> and the type of the reference that it refers to is ArrayList<HeavenlyBody>
The compiler expects method to return object of type ArrayList or more specific one (class that extends ArrayList). However, the type of moons variable returned from the method is less specific, i.e. List.
In this case, it is not important for the compiler what specific type does an instance assigned to moons variable have - the implementation you are asking about - only the variable type matters.
I hope this answers your question, if not please ask, I'll try to elaborate.
Important thing that you seem to be missing in your understanding is two parts of the following expression:
Type identifier = new SubType();
Beware, that identifier is a variable of type Type (and not directly of type SubType), and it can store a reference to the object of any other type, as long as that "other" type is a subtype of Type (including Type itself, as type is a sub-type of itself in Java).
Therefore:
private static ArrayList<HeavenlyBody> makingSetOfMoons() {
List<HeavenlyBody> moons = new ArrayList<>();
...
return moons;
}
will not compile, as the type of moons is List<HeavenlyBody>.
Q: Why this is designed so?
A: Because
in Java programming language, every variable and every expression has a type that is known at compile time.JSL - Chapter 4: Types, Values, and Variables
Imagine you had:
public ArrayList<SomeType> something(List<SomeType> list) {
...
return list;
}
You can observe, that List<SomeType> list can accept anything that is sub-type of it; however, if you, in this case, were allowed to return list (of type List<SomeType>), there is a big chance you would have received a runtime exception, as not every sub-type of List<E> can be converted to ArrayList<E>.
I understand that in the fields of a class, you can make the field type the name of another class and then in the constructor initialise that field by calling a new class of that type, i.e.
public class Auction {
private Bid bid;
}
public Auction {
bid = new Bid();
}
The main reason for doing this is, as I understand it, to access the methods of that class.
My question is I've noticed in some methods that there are local variables created that have a type of a different class with a variable name. What is the purpose of assigning a local variable name with a type of another class? Is this another way of just accessing those methods directly, even if it hasn't been done in the fields or constructor?
You can do this assignment only if type of the right part is-a type of the left part. So, for example, you can use methods of left part' type with realization from right part' type.
Number number = new Integer(10);
See also OOP in Java and Polymorphism in Java.
First of all, you need to learn some basics about OOP. We use Objects to model the problems and solve them in Object Oriented Programming.
These "type of a different class with a variable name" is an instance of a class, which is called an Object. We can assign a variable name to an object in order to use that object and its behaviors.
In a lambda, local variables need to be final, but instance variables don't. Why so?
The fundamental difference between a field and a local variable is that the local variable is copied when JVM creates a lambda instance. On the other hand, fields can be changed freely, because the changes to them are propagated to the outside class instance as well (their scope is the whole outside class, as Boris pointed out below).
The easiest way of thinking about anonymous classes, closures and labmdas is from the variable scope perspective; imagine a copy constructor added for all local variables you pass to a closure.
In a document of project lambda, State of the Lambda v4, under Section 7. Variable capture, it is mentioned that:
It is our intent to prohibit capture of mutable local variables. The
reason is that idioms like this:
int sum = 0;
list.forEach(e -> { sum += e.size(); });
are fundamentally serial; it is quite difficult to write lambda bodies
like this that do not have race conditions. Unless we are willing to
enforce—preferably at compile time—that such a function cannot escape
its capturing thread, this feature may well cause more trouble than it
solves.
Another thing to note here is, local variables are passed in the constructor of an inner class when you access them inside your inner class, and this won't work with non-final variable because value of non-final variables can be changed after construction.
While in case of an instance variable, the compiler passes a reference of the object and object reference will be used to access instance variables. So, it is not required in case of instance variables.
PS : It is worth mentioning that anonymous classes can access only final local variables (in Java SE 7), while in Java SE 8 you can access effectively final variables also inside lambda as well as inner classes.
In Java 8 in Action book, this situation is explained as:
You may be asking yourself why local variables have these restrictions.
First, there’s a key
difference in how instance and local variables are implemented behind the scenes. Instance
variables are stored on the heap, whereas local variables live on the stack. If a lambda could
access the local variable directly and the lambda were used in a thread, then the thread using the
lambda could try to access the variable after the thread that allocated the variable had
deallocated it. Hence, Java implements access to a free local variable as access to a copy of it
rather than access to the original variable. This makes no difference if the local variable is
assigned to only once—hence the restriction.
Second, this restriction also discourages typical imperative programming patterns (which, as we
explain in later chapters, prevent easy parallelization) that mutate an outer variable.
Because instance variables are always accessed through a field access operation on a reference to some object, i.e. some_expression.instance_variable. Even when you don't explicitly access it through dot notation, like instance_variable, it is implicitly treated as this.instance_variable (or if you're in an inner class accessing an outer class's instance variable, OuterClass.this.instance_variable, which is under the hood this.<hidden reference to outer this>.instance_variable).
Thus an instance variable is never directly accessed, and the real "variable" you're directly accessing is this (which is "effectively final" since it is not assignable), or a variable at the beginning of some other expression.
Putting up some concepts for future visitors:
Basically it all boils down to the point that compiler should be able to deterministically tell that lambda expression body is not working on a stale copy of the variables.
In case of local variables, compiler has no way to be sure that lambda expression body is not working on a stale copy of the variable unless that variable is final or effectively final, so local variables should be either final or effectively final.
Now, in case of instance fields, when you access an instance field inside the lambda expression then compiler will append a this to that variable access (if you have not done it explicitly) and since this is effectively final so compiler is sure that lambda expression body will always have the latest copy of the variable (please note that multi-threading is out of scope right now for this discussion). So, in case instance fields, compiler can tell that lambda body has latest copy of instance variable so instance variables need not to be final or effectively final. Please refer below screen shot from an Oracle slide:
Also, please note that if you are accessing an instance field in lambda expression and that is getting executed in multi-threaded environment then you could potentially run in problem.
It seems like you are asking about variables that you can reference from a lambda body.
From the JLS §15.27.2
Any local variable, formal parameter, or exception parameter used but not declared in a lambda expression must either be declared final or be effectively final (§4.12.4), or a compile-time error occurs where the use is attempted.
So you don't need to declare variables as final you just need to make sure that they are "effectively final". This is the same rule as applies to anonymous classes.
Within Lambda expressions you can use effectively final variables from the surrounding scope.
Effectively means that it is not mandatory to declare variable final but make sure you do not change its state within the lambda expresssion.
You can also use this within closures and using "this" means the enclosing object but not the lambda itself as closures are anonymous functions and they do not have class associated with them.
So when you use any field (let say private Integer i;)from the enclosing class which is not declared final and not effectively final it will still work as the compiler makes the trick on your behalf and insert "this" (this.i).
private Integer i = 0;
public void process(){
Consumer<Integer> c = (i)-> System.out.println(++this.i);
c.accept(i);
}
Here is a code example, as I didn't expect this either, I expected to be unable to modify anything outside my lambda
public class LambdaNonFinalExample {
static boolean odd = false;
public static void main(String[] args) throws Exception {
//boolean odd = false; - If declared inside the method then I get the expected "Effectively Final" compile error
runLambda(() -> odd = true);
System.out.println("Odd=" + odd);
}
public static void runLambda(Callable c) throws Exception {
c.call();
}
}
Output:
Odd=true
YES, you can change the member variables of the instance but you CANNOT change the instance itself just like when you handle variables.
Something like this as mentioned:
class Car {
public String name;
}
public void testLocal() {
int theLocal = 6;
Car bmw = new Car();
bmw.name = "BMW";
Stream.iterate(0, i -> i + 2).limit(2)
.forEach(i -> {
// bmw = new Car(); // LINE - 1;
bmw.name = "BMW NEW"; // LINE - 2;
System.out.println("Testing local variables: " + (theLocal + i));
});
// have to comment this to ensure it's `effectively final`;
// theLocal = 2;
}
The basic principle to restrict the local variables is about data and computation validity
If the lambda, evaluated by the second thread, were given the ability to mutate local variables. Even the ability to read the value of mutable local variables from a different thread would introduce the necessity for synchronization or the use of volatile in order to avoid reading stale data.
But as we know the principal purpose of the lambdas
Amongst the different reasons for this, the most pressing one for the Java platform is that they make it easier to distribute processing of collections over multiple threads.
Quite unlike local variables, local instance can be mutated, because it's shared globally. We can understand this better via the heap and stack difference:
Whenever an object is created, it’s always stored in the Heap space and stack memory contains the reference to it. Stack memory only contains local primitive variables and reference variables to objects in heap space.
So to sum up, there are two points I think really matter:
It's really hard to make the instance effectively final, which might cause lots of senseless burden (just imagine the deep-nested class);
the instance itself is already globally shared and lambda is also shareable among threads, so they can work together properly since we know we're handling the mutation and want to pass this mutation around;
Balance point here is clear: if you know what you are doing, you can do it easily but if not then the default restriction will help to avoid insidious bugs.
P.S. If the synchronization required in instance mutation, you can use directly the stream reduction methods or if there is dependency issue in instance mutation, you still can use thenApply or thenCompose in Function while mapping or methods similar.
First, there is a key difference in how local and instance variables are implemented behind the scenes. Instance variables are stored in the heap, whereas local variables stored in the stack.
If the lambda could access the local variable directly and the lambda was used in a thread, then the thread using the lambda could try to access the variable after the thread that allocated the variable had deallocated it.
In short: to ensure another thread does not override the original value, it is better to provide access to the copy variable rather than the original one.
This question already has answers here:
Why are only final variables accessible in anonymous class?
(15 answers)
Closed 6 years ago.
So in Java it's possible to instantiate an interface without creating an explicit class
public interface Foo {
public void OnNotify()
}
Say I do the following somewhere else, say in a method Subscribe
public void Subscribe()
{
final int someInt = 5;
Foo bar = new Foo() {
final int value = someInt;
#Override
public void OnNotify()
{
Log.d("Debug", "You are being notified that I hold the value " + value);
}
}
someObject.AddSubscription(bar);
}
This is used extensively in Android for setting listeners to events.
Why is this possible, and does this kind of instantiation have a special name? Is this related to lambda functions in some way perhaps?
And why do I need to make a 'final' variable if I want to give it to this instantiated interface to hold. Say for example I wanted to pass the current iteration 'i' of a for loop to identify what index of an array a subscription references. I need to declare a final variable to hold 'i', and then pass it into the instantiated interface.
Edit:
I'm still asking why I can instantiate an interface without making a class first, and what it's called. Not knowing what this is, there's no way I could have found the duplicate question, which doesn't cover what a Java anonymous class is.
Why is this possible, and does this kind of instantiation have a special name? Is this related to lambda functions in some way perhaps?
I don't know of any "special name" for this. I generally refer to it as a "interface implementation declaration." That's just me though, and maybe that's not accurate or correct.
I believe they are not, because aside from syntax differences, I look to lambdas as a method-class like structure, and this form is overriding methods from an object type. When passing an interface object, you're passing reference of a type.
And why do I need to make a 'final' variable if I want to give it to this instantiated interface to hold.
The way I have looked at it, and understood it to be, is because this declaration inline and not in a separate class doesn't quite change what an Interface still is. In the Java programming language, an interface is a reference type, similar to a class, that can contain only constants, method signatures, default methods, static methods, and nested types Link
An interface is required to have a constant, and to me final is a keyword that works similarly to the C/C++ keyword const in that it isn't holding the value but a reference to the type that you've declared. These values are immutable, preventing any copies and changes, as they only contain a reference to the location of the value.
So, overall, I believe that an interface declaration like how you illustrate is not working as declaring an instance of the actual interface class, but rather it's creating an object of that type and that object is a new location in memory that holds references to these methods and members (like a class).
Hope this helps some. I don't normally like to volunteer answers to something I am not 100% sure on, and wish this was a comment more (but lack the rep still for that), but hopefully it helps clear some things.
You can read the Java Language Specification here for more information on Interfaces too. Hope that helps.
In Java I can declare a variable, whose name is total same with its classname. I think it is a so confusing and strange design.
So I have a problem in the code snippet below: how can the compiler distinguish the ClassName, it is referenced the variable name or class name?
In the running result, the compiler references ClassName as a variable name.
class ClassName{}
public class Test {
public static void main(String[] args){
ClassName ClassName = new ClassName();
System.out.println(ClassName); //ClassName#18fb53f6
}
}
The compiler can tell by context. In the example you have given:
ClassName ClassName = new ClassName();
1 2 3
It can see that 1 is where a type name should be, so it knows you mean the class. Then, 2 is where a variable name is expected, so it knows that this should be the name of a variable. And 3 is coming after the new keyword with parentheses, so it must be the name of a class.
System.out.println( ClassName );
In this instance, ClassName is in the context of argument passing. A type name can't be passed as an argument, so you must mean the name of the variable.
To amuse yourself, you can change the print statement to:
System.out.println( ClassName.class );
Hover your mouse cursor on ClassName and you'll see that the compiler recognizes this as the name of a class. Then change it to:
System.out.println( ClassName.getClass() );
Hover your cursor again, and now you see that it recognizes it as the variable name. That's because .class can only be applied to a type name, while getClass() can only be applied to an object reference. The result of the print statement would be the same in both cases - but through different mechanisms.
So the compiler has no problem here. But you are right that it's not readable to humans. The convention is that names of variables and methods must start with a lowercase letter, while type names must start with an uppercase letter. Adhering to this convention will ensure that no such readability problems arise.
I can't say exactly why the authors of Java chose not to enforce this convention (that is, give a compiler error if type names started with a lowercase letter or variable/method names started with an uppercase), but I speculate that they didn't want to make anything an actual error unless it would actually cause an ambiguity for the compiler. Compilation errors are supposed to indicate a problem that makes the compiler unable to do its work.
how can the compiler distinguish the "Classname"
Because there are two components: The variable type and variable name. You declare a variable ClassName of type ClassName. Type always goes first. Classes are not first-class objects (meaning you can't have a reference to a class) unless you get into reflections (with the .class property).
Therefore, in the print statement:
System.out.println(ClassName);
That can only be the variable. System.out.println takes an object reference, and you have an object referred to by a variable named ClassName, therefore the compiler can resolve it.
The only case I can think that is ambiguous to the compiler is if the variable refers to an object which has an instance method of the same name as a static method on the class.
public class SomeClass {
public void aMethod() {
System.out.println("A method!");
}
public static void aMethod() {
System.out.println("Static version!");
}
}
public class TestClass {
public static void main (String[] args) {
SomeClass SomeClass = new SomeClass();
SomeClass.aMethod(); // does this call the instance method or the static method?
}
}
I am sure the compiler will detect the ambiguity and handle it in some specified manner (in the Java spec). Probably one of:
Don't allow a static and instance method to have the same name.
Allow it, and when resolving the reference at compile-time, prefer the instance method.
Allow it, and when resolving the reference at compile-time, prefer the static method.
If either of the last 2, I imagine a compiler warning would be logged.
Now that the compiler question is aside, the only other consumer of the code is human beings. Compilers may be able to rely on specifications to guarantee rationale behavior, but humans can't. We get confused easily. The best advice I have for that is simply, don't do it!
There is absolutely no reason to name a variable identically to a class. In fact, most Java coding style conventions I have seen use lowerCamelCase to name variables and methods and UpperCamelCase to name classes, so there is no way for them to collide unless you deviated from the standards.
If I encountered code like that in a project I was working on, I would immediately rename the variable before doing anything else.
For my ambiguous case of an instance and static method of the same name, there just might be a human lesson in there too: don't do it!
Java has a lot of rules to force you to do things that are logical and make code easy to follow, but at the end of the day, it's still code and you can write any code you want. No language spec or compiler can prevent you from writing confusing code.
ClassName ClassName = new ClassName();
If you study compiler design course, you will know there is a Lexical Analysis step. At this step, you will write a grammar for your language. for example:
ClassName variableName = new ClassName();
So example above, compiler can understand second ClassName is variable.
When you do something like:
ClassName.doSomething();
Java will understand ClassName as variable rather than a class. And this design won't have any limitation. doSomething() can be both static method or just a instance method.
If Java understands ClassName here as class, so doSomething() cannot be a instance method. Maybe because this so Java creator has chosen above design: ClassName as a variable.
But what the problem if a variable name cannot be same name with their class. so the following example:
ClassA ClassB = new ClassA();
ClassB.callMethodInClassB(); // should compile error or not ???!!!
The problem still be here. The misleading still exist. So the new design should be:
No variable name should not has same name with **any** class name.
And you will see, this statement makes one language more complicate to understand and not so well-define. From above proofs, I think when you do something such as: A A = new A(); understand A as variable is a best way in language design.
Hope this help :)