I'm a newbie to Java.
I have provided a short snippet from my code for BFS.
public int bfs(Person p, Person q) {
private HashMap<Person, boolean> marked;
private int count;
marked = new marked<Person, boolean>();
count = new int;
}
According to Eclipse, I have an error on each of the last 4 lines.
Syntax Error: insert "Dimensions" to complete expression/referencetype.
I would appreciate any input/advice!
Cause of this error -You are trying to pass a primitive object into a generic type declaration whereas generic types always expect a Wrapper Class object. So please use 'Boolean' instead of 'boolean' in your code i.e. 'B' in caps.
You need to use the wrapper object not the primitive. Use Boolean instead of boolean.
Satyendra Sharma's answer is absolutely correct, but here's some reasoning of what exactly the error message is saying.
The error is caused by using a primitive type, which cannot be used as a generic type argument. For instance, List<boolean> is incorrect, whereas List<Boolean> is correct. Wrapper classes can be used to wrap the primitive values and yield a reference type, which can be used with generics.
Insert dimensions? What?
The message "Insert dimensions to complete expression/referenceType" is probably because in order for the expression to become valid, the only valid token here is a set of square brackets.
For instance,
HashMap<Person, boolean[]> marked;
will just compile fine. This is because, unlike a boolean, a boolean[] is an object.
Generic are resolved during compile time and during runtime their no context about the generic used in your code. The Object is than type cast into the class type provided against the generic type. Now both primitive and object are completely unrelated entities in java. Direct time-cast of Object to primitive type isn't possible in java. For this reason the use of primitive type in generic is disallowed and eclipse gives this warning.
First I would suggest you start reading a Java tutorial...
https://docs.oracle.com/javase/tutorial/java/TOC.html
For your issues specifically:
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
https://docs.oracle.com/javase/tutorial/java/javaOO/objectcreation.html
https://docs.oracle.com/javase/tutorial/java/javaOO/variables.html
As for your code, you can initialize your variables right when you declare them:
Map<Person, Boolean> marked = new HashMap<Person, Boolean>();
int count = 0; // or whatever initial value
It seems that this snippet is throwing around random keywords without any understanding - I would suggest a Java tutorial. First of all, generics are one of the main uses for boxing. boolean or any other primitives (you can recognise these by the fact that their identifiers are in lower-case and most IDEs will highlight them) cannot be used as a generic type, and their capitalised equivalent must be used (a simple wrapper class). Here, use HashMap<Person, Boolean>.
I'm not sure what is meant by marked = new marked... - clearly, marked is not a type and cannot be used in this context. new x(params) initialises an object of type x, passing its constructor params. new x<generics>(params) is the same but the generic type(s) of x are generics.
Finally, new int is not at all valid - see my explanation above. Primitives are not objects, which means initialising them is meaningless and therefore invalid. Also, what do you expect this expression to yield? Something of type int, but you are not specifying which int. The correct syntax is a literal: count = x; where x is some integer within the range of int.
As a side note, your method has an unclear name and variables may be initialised in the same line you declare them to simplify code.
Visit Cannot Instantiate Generic Types with Primitive Types
Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.
The type parameter, V, actually also K, which is declared in HashMap<K,V>, will be replaced with Object after erasing, because they are unbounded. While primitive type can not be store as Object.
Related
I'm a newbie to Java.
I have provided a short snippet from my code for BFS.
public int bfs(Person p, Person q) {
private HashMap<Person, boolean> marked;
private int count;
marked = new marked<Person, boolean>();
count = new int;
}
According to Eclipse, I have an error on each of the last 4 lines.
Syntax Error: insert "Dimensions" to complete expression/referencetype.
I would appreciate any input/advice!
Cause of this error -You are trying to pass a primitive object into a generic type declaration whereas generic types always expect a Wrapper Class object. So please use 'Boolean' instead of 'boolean' in your code i.e. 'B' in caps.
You need to use the wrapper object not the primitive. Use Boolean instead of boolean.
Satyendra Sharma's answer is absolutely correct, but here's some reasoning of what exactly the error message is saying.
The error is caused by using a primitive type, which cannot be used as a generic type argument. For instance, List<boolean> is incorrect, whereas List<Boolean> is correct. Wrapper classes can be used to wrap the primitive values and yield a reference type, which can be used with generics.
Insert dimensions? What?
The message "Insert dimensions to complete expression/referenceType" is probably because in order for the expression to become valid, the only valid token here is a set of square brackets.
For instance,
HashMap<Person, boolean[]> marked;
will just compile fine. This is because, unlike a boolean, a boolean[] is an object.
Generic are resolved during compile time and during runtime their no context about the generic used in your code. The Object is than type cast into the class type provided against the generic type. Now both primitive and object are completely unrelated entities in java. Direct time-cast of Object to primitive type isn't possible in java. For this reason the use of primitive type in generic is disallowed and eclipse gives this warning.
First I would suggest you start reading a Java tutorial...
https://docs.oracle.com/javase/tutorial/java/TOC.html
For your issues specifically:
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
https://docs.oracle.com/javase/tutorial/java/javaOO/objectcreation.html
https://docs.oracle.com/javase/tutorial/java/javaOO/variables.html
As for your code, you can initialize your variables right when you declare them:
Map<Person, Boolean> marked = new HashMap<Person, Boolean>();
int count = 0; // or whatever initial value
It seems that this snippet is throwing around random keywords without any understanding - I would suggest a Java tutorial. First of all, generics are one of the main uses for boxing. boolean or any other primitives (you can recognise these by the fact that their identifiers are in lower-case and most IDEs will highlight them) cannot be used as a generic type, and their capitalised equivalent must be used (a simple wrapper class). Here, use HashMap<Person, Boolean>.
I'm not sure what is meant by marked = new marked... - clearly, marked is not a type and cannot be used in this context. new x(params) initialises an object of type x, passing its constructor params. new x<generics>(params) is the same but the generic type(s) of x are generics.
Finally, new int is not at all valid - see my explanation above. Primitives are not objects, which means initialising them is meaningless and therefore invalid. Also, what do you expect this expression to yield? Something of type int, but you are not specifying which int. The correct syntax is a literal: count = x; where x is some integer within the range of int.
As a side note, your method has an unclear name and variables may be initialised in the same line you declare them to simplify code.
Visit Cannot Instantiate Generic Types with Primitive Types
Replace all type parameters in generic types with their bounds or Object if the type parameters are unbounded. The produced bytecode, therefore, contains only ordinary classes, interfaces, and methods.
The type parameter, V, actually also K, which is declared in HashMap<K,V>, will be replaced with Object after erasing, because they are unbounded. While primitive type can not be store as Object.
I thought I knew what I was doing with generics, but apparently not.
ArraySetList<char> setA = new ArraySetList<char>();
When compiled gives:
error: unexpected type
ArraySetList<char> setA = new ArraySetList<char>();
^
required: reference
found: char
As well as the same error for all subsequent char's. I'm wondering how to declare a new ArraySetList of characters.
Here are all my files.
http://pastebin.com/4h37Xvu4 // ArraySetList (extends ArrayUnsortedList)
http://pastebin.com/FxmynzkC // Driver
http://pastebin.com/CgVA0zjY //ArrayUnsortedList (implements ListInterface)
http://pastebin.com/3iXrCsCc //ListInterface\
Java Generics work for objects and not for primitive data types. If you, however, need to store primitive data types, you will need to use their corresponding wrapper class objects.
These classes just "wrap" around the primitive data type to give them an object appearance.
For char, the corresponding wrapper class is Character and hence, you must write your line of code as so:
ArraySetList<Character> setA = new ArraySetList<Character>();
Please read: http://docs.oracle.com/javase/tutorial/java/data/numberclasses.html
When you add elements, however, you will add normal char. That is because Java will automatically convert it into Character for you and back to char automatically, if need be. This is called auto-boxing conversion.
Autoboxing is the automatic conversion that the Java compiler makes
between the primitive types and their corresponding object wrapper
classes. For example, converting an int to an Integer, a double to a
Double, and so on. If the conversion goes the other way, this is
called unboxing.
source: http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
Generic type arguments require reference types (or wilcards).
You can't use primitive types (for more see restrictions);
ArraySetList<Character> setA = new ArraySetList<Character>();
Read JLS 4.5.1 Type Arguments and Wildcards for usable types
If I write:
int x = 7;
Can we conclude that the value type of 7 is int and therefore the type of x is also int?
What is 'int' indicating here? That the value is int or that 7 is an int?
int refers to x. It is indicating the type of the variable x. This is also informative of the type of the values that would be stored there.
int x =7;
Consists of 2 parts.
One is:
int x;
That declares x as an int in this scope. This shows that int refers to x.
The other part of the expression is:
x=7;
That actually assigns the int value 7 to x.Of course the assignment needs to be valid.So the value should be of a suitable type.
It also would be valid to omit the assignment in a program (if for example you do not use this variable.)
On the other hand you cannot omit the declaration since java is strongly typed.
For example writing:
y=8;
Does not give enough information unless y is declared.
y could be for example an int , Integer , long or Long.
What y is depends on its declaration.
It indicates that the variable x is of type int.
The expression 7 also happens to have type int, therefore the example is not that interesting.
Consider a more interesting example:
List<String> myList = new ArrayList<>();
Here, the compiler could infer that the type of new ArrayList<>() on the right hand side is ArrayList<String>. However, we might want to hide the concrete implementing class ArrayList, and instead declare myList to be of a more general type List<String>, which is a supertype of ArrayList<String>. This is useful if we want to prevent abstraction leak from the members of a class, or if we use myList as a local variable, and for some reason want to set it to an LinkedList later.
That's all I had to say on the question itself, but I want to give some context, and I want to argue that Java's current syntax is actually not too bad.
This syntax might seem verbose, one might think that one can often omit the type declaration on the left hand side. However, consider a language with stronger type inference.
For example, a closely related statically strongly typed language Scala tends to rely more on type inference. For example, if you write
var myList = List("foo", "bar")
it will automatically infer that myList is a variable of type List[String].
But this often leads to unwanted results. For example, given the assignment
var myList = List.empty
the Scala compiler would happily infer that the right hand side is a List[Nothing], where Nothing is a special type that signifies absurd impossible results "returned" by thrown Exceptions and Errors which break the normal program flow. You can't do anything with this variable. In order to make this variable useful, we have to write:
var myList: List[String] = List.empty
Now Scala compiler would understand that myList is supposed to be List[String], which is more general than the type inferred from the right hand side. As you can see: now you have both val keyword and an additional List[String]-type declaration on the left hand side, which is not necessarily much shorter than the corresponding Java version. It is actually longer, despite all the fancy type-inference magic. So, Java's syntax for variable declarations is... OK, at least it's not trivial to make it much better.
I thought I knew what I was doing with generics, but apparently not.
ArraySetList<char> setA = new ArraySetList<char>();
When compiled gives:
error: unexpected type
ArraySetList<char> setA = new ArraySetList<char>();
^
required: reference
found: char
As well as the same error for all subsequent char's. I'm wondering how to declare a new ArraySetList of characters.
Here are all my files.
http://pastebin.com/4h37Xvu4 // ArraySetList (extends ArrayUnsortedList)
http://pastebin.com/FxmynzkC // Driver
http://pastebin.com/CgVA0zjY //ArrayUnsortedList (implements ListInterface)
http://pastebin.com/3iXrCsCc //ListInterface\
Java Generics work for objects and not for primitive data types. If you, however, need to store primitive data types, you will need to use their corresponding wrapper class objects.
These classes just "wrap" around the primitive data type to give them an object appearance.
For char, the corresponding wrapper class is Character and hence, you must write your line of code as so:
ArraySetList<Character> setA = new ArraySetList<Character>();
Please read: http://docs.oracle.com/javase/tutorial/java/data/numberclasses.html
When you add elements, however, you will add normal char. That is because Java will automatically convert it into Character for you and back to char automatically, if need be. This is called auto-boxing conversion.
Autoboxing is the automatic conversion that the Java compiler makes
between the primitive types and their corresponding object wrapper
classes. For example, converting an int to an Integer, a double to a
Double, and so on. If the conversion goes the other way, this is
called unboxing.
source: http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
Generic type arguments require reference types (or wilcards).
You can't use primitive types (for more see restrictions);
ArraySetList<Character> setA = new ArraySetList<Character>();
Read JLS 4.5.1 Type Arguments and Wildcards for usable types
What is the difference between compile time and run time type of any object in Java ? I am reading Effective Java book and Joshua Bloch mentions about compile time type and run time types of array instances in Item 26 many times mainly to describe that suppressing cast warnings can be safe sometimes.
// Appropriate suppression of unchecked warning
public E pop() {
if (size == 0)
throw new EmptyStackException();
// push requires elements to be of type E, so cast is correct
#SuppressWarnings("unchecked") E result = (E) elements[--size];
elements[size] = null; // Eliminate obsolete reference
return result;
}
Here the author is talking about these different types of types in context of arrays . But through this question I would like to understand the difference between compile time types vs run time types for any type of object .
Java is a statically typed language, so the compiler will attempt to determine the types of everything and make sure that everything is type safe. Unfortunately static type inference is inherently limited. The compiler has to be conservative, and is also unable to see runtime information. Therefore, it will be unable to prove that certain code is typesafe, even if it really is.
The run time type refers to the actual type of the variable at runtime. As the programmer, you hopefully know this better than the compiler, so you can suppress warnings when you know that it is safe to do so.
For example, consider the following code (which will not compile)
public class typetest{
public static void main(String[] args){
Object x = args;
String[] y = x;
System.out.println(y[0])
}
}
The variable x will always have type String[], but the compiler isn't able to figure this out. Therefore, you need an explicit cast when assigning it to y.
An example
Number x;
if (userInput.equals("integer")) {
x = new Integer(5);
} else {
x = new Float(3.14);
}
There are two types related to x
the type of the name x. In the example, it's Number. This is determined at compile-time and can never change, hence it's the static type
the type of the value x refers to. In the example, it can be Integer or Float, depending on some external condition. The compiler cannot know the type at compilation time. It is determined at runtime (hence dynamic type), and may change multiple times, as long as it's a subclass of the static type.
Java is statically typed. That means that every expression (including variables) in the language has a type that is known at compile time according to the rules of the language. This is known as the static type (what you call "compile-time type"). The types in Java are the primitive types and the reference types.
Also, each object at runtime in Java has a "class" (here, "class" includes the fictitious array "classes"), which is known at runtime. The class of an object is the class that an object was created with.
Part of the confusion comes from the fact that each class (and interface and array type) in Java has a corresponding reference type, with the name of the class (or interface or array type). The value of a reference type is a reference, which can either be null or point to an object. The Java language is designed so that a reference of reference type X, if not null will always point to an object whose class is the class X or a subclass thereof (or for interfaces, whose class implements the interface X).
Note that the runtime class applies objects, but objects are not values in Java. Types, on the other hand, apply to variables and expressions, which are compile-time concepts. A variable or expression can never have the value of an object, because there are no object types; it can have a value of a reference that points to an object.
I think of "compile time type" as ANY type a variable can be shown to have at compile time. That would include the declared class, any superclasses, and any implemented interfaces.
At runtime, a given object only has one lowest-level class; it can legally be cast to or assigned to a variable of that class, but also to any variable of any of its subclasses or implemented interfaces. The compiler will (often, anyway) allow you to cast it to anything, but the runtime will throw an exception if you attempt to assign something that is not legal.
Once an object is assigned to the variable, then the compiler will treat it as though it is of the type of the variable. So another use of "compile time" could be the variable type, and you can get around that at compile time by casting to a different type as long as you know the cast will be legal at runtime.
If I speak of just one type, I think of the 'runtime type' of a variable as the actual bottom (top?) level subclass of the variable; the lowest sub-class to which it could be cast. But I also routinely think of any object as an instantiation of any of its legal types.
Hope that helps.
Java arrays are so called "covariant", which means a String[] is a subtype of Object[], and type rules are checked at COMPILE time.
Java arrays check at RUNTIME if the object (e.g. String, Integer, WhatEver) you would like to store into it, is compatible with the type the array actually created with.
For example:
String[] strings = new String[2];
strings[0] = "I am text";
Object[] objects = strings;
objects[1] = new Date(); // Compiles, but at runtime you get an ArrayStoreException