Object used parameter in a method - java

I'm a Java newbie so excuse me if this sounds like a dumb question.
Can someone explain to me what is going on with this method?
public static void policyInNoFaultState( AutoPolicy policy ) <===line in question
Is "policy" of object type from AutoPolicy? therefore policy inherits everything AoutoPolicy has?
Is this the reason I can use the "Dot" command exp. policy.getAccountNumber(), policy.getMakeAndModel()
I pasted part of the program I think applies to this question.
I appreciate any help you can give.
//Creating AutoPolicy ojbects
AutoPolicy policy1 = new AutoPolicy(11111111,"Toyota Camary", "NJ");
AutoPolicy policy2 = new AutoPolicy(22222222, "Ford Fusion", "ME");
//Creating policyInNoFaultState method to display results
public static void policyInNoFaultState( AutoPolicy policy ){
System.out.println("The auto policy:");
System.out.printf("Account #: %d; Car: %s;%nState %s %s a no-fault state%n%n",
policy.getAccountNumber(), policy.getMakeAndModel(),policy.getState(),(policy.isNoFaultState() ? "is": "is not"));
}//End of policyInNoFaultState

A class in Java defines a type and basically acts as template for all instances (objects) created from that class. This template defines data (fields) and behavior (methods) available for all of instances of this type. "Static" members of the type are shared between all instances and non-static members (also called "instance members") are distinct between instances.
Consider the following simple example (beware, this makes no promises about best practices how to define and use classes and instances):
class MyType {
public static int Shared = 42;
public int NonShared;
public void Print() {
System.out.println("This is me: " + (Shared + NonShared));
}
}
You can create several instances of this class which will all share the same shared field but each have their own value for the instance field:
MyType a = new MyType();
MyType b = new MyType();
a.NonShared = 21;
b.NonShared = 84;
a.Print(); // prints "This is me: 63"
b.Print(); // prints "This is me: 126"
a.Shared = 0;
a.Print(); // now prints "This is me: 21"
b.Print(); // now prints "This is me: 84"
a and b are instances of class/type MyType. In a way, 42, 21, and 84 are instances of the type int.
When you define a method to act on values, you have to specify which kind of values the method should be able to handle. This is done by specifying the type for each of its parameters. Let's have a look at another arbitrary example method:
static String format(MyType object, String info) {
return info + ".NonShared = " + object.NonShared;
}
Above method returns a single instance of type String and works one two parameters of type MyType and String respectively. This is required so that the compiler knows which members (fields or methods) are available for each parameter. Otherwise calling object.NonShared would not be possible.
MyType c = new MyType();
c.NonShared = 7;
String formatted = format(c, "formatting");
System.out.println(formatted); // prints "formatting.NonShared = 7"
Note that in this simple case, the type of variable c matches the type of the parameter object exactly. This is not required, you can pass any subtype (or "child class") to the parameter. The parameter's type merely defines the minimum number of members that must be supported by any argument that is passed to the function. You can think of it as a contract between the input parameter and the processing function.
static Integer firstValue(Collection<Integer> list) {
list.get(0);
}
List<Integers> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
firstValue(numbers);
The above code will not work. It will not even compile! Even though numbers is an instance of the interface type List with concrete implementation type ArrayList and has an instance-method get, this is not available (nor known) inside the method, which can only work with Collection types. The Collection type does not define an get method, despite implementations of it (sub types, child classes) might provide it.
By using the smallest possible type for any given task, you gain a lot of flexibility. All collections implement the add method. By defining a method which can work with Collection, you can pass in any implementation which adheres to this type and modify it:
static void addValue(Collection<Integer> bag) {
bag.add(4);
}
List<Integer> list = new ArrayList<>();
Set<Integer> set = new HashSet<>();
Deque<Integer> stack = new ArrayDeque<>();
Queue<Integer> queue = new PriorityQueue<>();
addValue(list);
addValue(set);
addValue(stack);
addValue(queue);
I hope this clears things up! If there is any detail that is still unclear, please point it out in the comments and I will try to extend my answer with further points.

Here "policy" is holding the reference number of an object of "AutoPolicy" type. That is pointing the object passed in parameter.
For better understanding you can go through topic "pass by value and pass by reference in java"

Related

How to remember things when it comes to mixture of polymorphism, Inheritance, overloading, overriding, Generics as well as Casting

I was preparing for Java Certification Exam and there are few scenarios which gets very complicated sometimes when to comes to a mixture of polymorphism, Inheritance, overloading, overriding, Generics as well as Casting.
I am stuck with understanding these examples mentioned below :
// Tree is the base class
class Tree {
String type = "unknown";
String getTreeString() {
return "Tree";
}
}
// DeciduousTree is a subclass of Tree
class DeciduousTree extends Tree {
String type = "deciduous";
#Override
String getTreeString() {
return "Leafy Tree";
}
}
// FruitTree is a subclass of Tree
class FruitTree extends Tree {
String type = "fruit";
#Override
String getTreeString() {
return "Fruit Tree";
}
}
public class UpcastExamples {
public static void main(String[] args) {
UpcastExamples upex = new UpcastExamples();
// Create two specific trees
Tree tree = new Tree();
Tree mapleTree = new DeciduousTree();
Tree appleTree = new FruitTree();
// we upcast deciduousTree to its parent class
Tree genericTreeMaple = (Tree) mapleTree;
Tree genericTreeApple = (Tree) appleTree;
Tree genericTreeTree = (Tree) tree;
// Print mapleTree's type
System.out.println("Tree type = " + mapleTree.type);
// Let's upcast to use the generic Tree's type..
System.out.println("Tree type = " + (genericTreeMaple.type));
// Print Fruit Tree's type
System.out.println("Tree type = " + appleTree.type);
// Upcasting to pass object as a parameter
upex.printTreeType(genericTreeTree);
upex.printTreeType(genericTreeMaple);
upex.printTreeType(genericTreeApple);
upex.printTreeType(tree);
upex.printTreeType(mapleTree);
upex.printTreeType(appleTree);
}
public void printTreeType(Tree tree) {
System.out.println("Tree type = " + tree.getTreeString());
}
}
I expected these upex.printTreeType(genericTreeMaple);upex.printTreeType(genericTreeApple); to print Tree since they are upcasted to Tree(Base Class) but somehow it grabs the methods of its child classes (I know they are overriden) but the same thing when implemented via method overloading then
Animal genericDog = new Dog();Animal genericCat = new Cat(); will hold on to the method of the parent's class.
I tried to remember like this parentClass p = new childClass() will always refer methods of parentClass but it seems to fail during overriding and upcasting.
Also, there are few other things mentioned below that I could not understand, I don't just want to memorize stuffs.
Here BaseClass class is the parent class
And NextClass inherits the BaseClass
BaseClass[] myNextArray = new NextClass[6];
BaseClass[] myNextArray2 = new BaseClass[6];
//Allows this:
NextClass[] nextArray = (NextClass[]) myNextArray; //Line 1
//But doesn't allows this:
NextClass[] nextArray2 = (NextClass[]) myNextArray2;
Do I have to memorize that Array of SubClass is not equal to Array of SuperClass in Java but how come it allows Line 1 is also a big doubt
In Java, each object (which includes arrays) has a type that is determined upon construction, e.g. using the new operator. This type never changes.
Variables only contain references to objects. Think of a remote control. You can refer to an object using a variable having a broader type, i.e. the type of a superclass or interface of the object. But this doesn’t change the type of the object itself.
Therefore, when you invoke an overridable method, you will always invoke the most specific method of the object’s actual type. Further, a type cast will succeed if the object’s actual type is compatible. The variable’s reference type does not tell whether the type cast will succeed, as otherwise, we wouldn’t need the runtime check at all¹.
When you initialize a variable like
BaseClass[] myNextArray = new NextClass[6];
the object’s actual type is NextClass[], hence, a subsequent type cast to NextClass[] can succeed. In contrast, using
BaseClass[] myNextArray2 = new BaseClass[6];
the object’s actual type is BaseClass[], hence, a type cast to NextClass[] will fail.
Note that it is possible to change a reference variable to let it point to a different object, so whether casting the reference to a specific type will succeed may change too.
BaseClass[] myNextArray = new NextClass[6];
NextClass[] nextArray = (NextClass[]) myNextArray; // succeeds
myNextArray = new BaseClass[6]; // let myNextArray refer to a different object
nextArray = (NextClass[]) myNextArray; // will fail
¹ The only exception to the rule is that the compiler will reject certain type casts that can be proven at compile-time to be impossible to succeed, like trying to cast an Integer to a String.

How is upcasted object stored in Heap in Java

So I wrote a simple java code here as shown below.
package com.example.aakash;
public abstract class Book {
String title;
String author;
Book(String t,String a){
title=t;
author=a;
}
abstract void display();
}
So Book is an abstract class which is to be extended by two different class called MyBook and ABook class as shown below.
package com.example.aakash;
public class MyBook extends Book {
private int price;
MyBook(String t, String a,int p) {
super(t, a);
price = p;
}
#Override
public void display(){
System.out.println("Title: "+title);
System.out.println("Author: "+author);
System.out.println("Price: "+price);
}
}
package com.example.aakash;
public class ABook extends Book {
private int price;
ABook(String t, String a,int p) {
super(t, a);
price = p;
}
#Override
public void display(){
System.out.println("Title: "+title);
System.out.println("Author: "+author);
System.out.println("Price: "+price);
}
}
package com.example.aakash;
import java.util.ArrayList;
public class Main {
public static void main(String[] args){
ArrayList<Book> myArray = new ArrayList<Book>();
String bookName = "Book";
for(int i=1;i<=10;i++){
if(i%2==0){
String tempBook = bookName + i;
String author = "Author2";
Book temp = new MyBook(tempBook,author,i*50);
myArray.add(temp);
}else{
String tempBook = bookName + i;
String author = "Author1";
Book temp = new ABook(tempBook,author,i*50);
myArray.add(temp);
}
}
for(int i=0;i<10;i++){
Book temp = myArray.get(i);
temp.display();
System.out.println("--------------------------------------------------");
}
myArray.get(5).display();
}
}
Okay so when I run this program, the display method print the right book,author and price every single time. Just the way they are stored. However at runtime, JVM doesn't know that weather a Book object on the array list is of type MyBook or ABook. So my question is how does calling the display method print the right book every single time. How does ArrayList of Book object get stored on heap? (i.e all objects get store in heap in Java) Does it store it as upcasted Book object. Or does it store it as the actual MyBook and ABook type of object so that when display method is called, JVM explicitly knows that weather the method on MyBook or ABook is to be called?
P.S. Yes example is kind of bad but suppose I don't even have similar display method on MyBook and ABook. Even then the JVM still executes the correct display method. So please explain what is going on in JVM when up-casting is done.
The concrete object is an ABook declared as Book.
Which display method select is resolved at runtime, not a compile time.
From JLS:
If the method that is to be invoked is an instance method, the actual
method to be invoked will be determined at run time, using dynamic
method lookup (§15.12.4).
Basically it means that the real instance type is taken at runtime. If the method is overwritten in that class this method is executed, if it is not overwritten the method of the super class is invoked.
You are mixing up objects and references. You never store an object in an ArrayList, you are just storing a reference to an object. A reference might have a broader type than the object it is pointing to, but that never changes the actual type of the object.
In fact, due to type erasure, an ArrayList<Book> doesn’t even contain references of the type Book, it has no knowledge about it. It only contains references of type Object, but that’s sufficient for the ArrayList to work as all it needs, is the method boolean equals(Object) that is declared in java.lang.Object. Since the type of the reference does not change the type of the actual object, invoking equals on an object via a reference typed as Object will still invoke the most specific method of the actual type, if the equals method has been overridden.
You may also store the same object multiple times in a List, whereas “store an object” is a colloquial term which you always have to translate to “store a reference to that object” for yourself. There’s still only one object if you do that and the list will just contain multiple references to it. Modifying that object through one of these references will become visible through all other references immediately.
The type of an object is fixed right when it is created and stored within the object in an implementation specific manner. That’s also the reason why a runtime type cast narrowing the type to a more specific one can verify the correctness. The cast is not changing the type of the object, it’s only creating a new reference to the same object with a more specific type out from a reference with a broader type, after the correctness has been proven. This also happens implicitly when retrieving a reference from the ArrayList<Book>; the reference of type Object stored in the list is converted to the reference of type Book you will receive.
This concept is called Polymorphism.
ABook is a Book
MyBook is a Book
You can have an ArrayList and have inside objects of ABook and MyBook.
But everytime that you get an object of this ArrayList, you can only call book's method, unless you make a downcast to one of this subclass. But you have to be sure of the subclass before the cast, because you might get an CastException.
Finally, if you call an override method, at runtime he will always call the object method. At runtime he we always call the objects method.

Is-a relationship with parameterized references

This has probably been asked before but i haven't been able to find a question.
I would like to understand the underlying reasons why does the following block of code not compile:
public class Box<T> {
private T value;
public Box(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public static void main(String[] args) {
Box<Integer> i = new Box<Integer>(13);
// does not compile
Box<Object> o = i;
}
}
One way to look at it is, let's assume Box defined a void setValue(T val) method.
Box<Object> o = i;
o.setValue("a string");
Integer x = i.getValue(); // ?!
The problem is mentioned in java documentation here (it is similar to Vlad's answer):
https://docs.oracle.com/javase/tutorial/extra/generics/subtype.html
Let's test your understanding of generics. Is the following code snippet legal?
List<String> ls = new ArrayList<String>(); // 1
List<Object> lo = ls; // 2
Line 1 is certainly legal. The trickier part of the question is line 2. This boils down to the question: is a List of String a List of Object. Most people instinctively answer, "Sure!"
Well, take a look at the next few lines:
lo.add(new Object()); // 3
String s = ls.get(0); // 4: Attempts to assign an Object to a String!
Here we've aliased ls and lo. Accessing ls, a list of String, through the alias lo, we can insert arbitrary objects into it. As a result ls does not hold just Strings anymore, and when we try and get something out of it, we get a rude surprise.
Firstly you cannot cast parameterized types. Check this oracle doc.
Typically, you cannot cast to a parameterized type unless it is
parameterized by unbounded wildcards. For example:
List li = new ArrayList<>();
List ln = (List) li; // compile-time error
Hence the line Box<Object> o = i; causes compile time error.
Even though while creating Box object you have not specified the generic parameter, but using constructor parameter type java Type inference the constructing object's type.
You can assign any reference to an Object reference but when generics kicks in, the exact generic type is matched at compile time. Hence it's not working. If you change to Box<? extends Object> o = i; it'll work since the generic type matches the contained type.

How do parameterized methods resolve <T> if it's not an input parameter?

How are references to << T >> handled by the compiler in the following code, since the method takes no parameters that would allow inference of T? Are any restrictions being placed on what type of object can be placed into the list? Is a cast even taking place on the line where I add the String to the list? My first thought is that without anything to infer T from, T becomes an Object type. Thanks in advance.
public class App {
private <T> void parameterizedMethod()
{
List<T> list = new ArrayList<>();
for(int i = 0; i < 10; i++)
{
list.add((T)new String()); //is a cast actually occurring here?
}
}
public App()
{
parameterizedMethod();
}
public static void main(String[] args) {
new App();
}
}
This is initially determined by 18.1.3:
When inference begins, a bound set is typically generated from a list of type parameter declarations P1, ..., Pp and associated inference variables α1, ..., αp. Such a bound set is constructed as follows. For each l (1 ≤ l ≤ p):
If Pl has no TypeBound, the bound αl <: Object appears in the set.
Otherwise, for each type T delimited by & in the TypeBound, the bound αl <: T[P1:=α1, ..., Pp:=αp] appears in the set; [...].
At the end of inference, the bound set gets "resolved" to the inferred type. Without any additional context, the bound set will only consist of the initial bounds based on the declaration of the type parameter.
A bound with a form like αl <: Object means αl (an inference variable) is Object or a subtype of Object. This bound is resolved to Object.
So in your case, yes, Object is inferred.
If we declared a type bound:
private <T extends SomeType> void parameterizedMethod()
then SomeType will be inferred.
No cast actually happens in this case (erasure). That's why it's "unchecked". A cast only happens when the object is exposed due to e.g.:
<T> T parameterizedMethodWithAResult()
{
return (T) new String();
}
// the cast happens out here
Integer i = parameterizedMethodWithAResult();
// parameterizedMethodWithAResult returns Object actually,
// and we are implicitly doing this:
Integer i = (Integer) parameterizedMethodWithAResult();
Are any restrictions being placed on what type of object can be placed into the list?
Semantically (compile-time), yes. And note that the restriction is determined outside the method. Inside the method, we don't know what that restriction actually is. So we should not be putting String in a List<T>. We don't know what T is.
Practically (run-time), no. It's just a List and there's no checked cast. parameterizedMethod won't cause an exception...but that only holds for this kind of isolated example. This kind of code may very well lead to issues.
Inside the method body, Java provides us no way to get any information about the substitution for T, so how can we do anything useful with T?
Sometimes, T is not really important to the method body; it's just more convenient for the caller
public static List<T> emptyList(){...}
List<String> emptyStringList = emptyList();
But if T is important to method body, there must be an out-of-band protocol, not enforceable by the compiler, that both the caller and the callee must obey. For example
class Conf
<T> T get(String key)
//
<conf>
<param name="size" type="int" ...
//
String name = conf.get("name");
Integer size = conf.get("size");
The API uses <T> here just so that the caller doesn't need to do an explicit cast. It is the caller's responsibility to ensure that the correct T is supplied.
In your example, the callee assumes that T is a supertype of String; the caller must uphold that assumption. It would be nice if such constraint can be expressed to the compiler as
<T super String> void parameterizedMethod()
{
List<T> list
...
list.add( new String() ); // obviously correct; no cast is needed
}
//
this.<Integer>parameterizedMethod(); // compile error
unfortunately, java does not support <T super Foo> ... :) So you need to javadoc the constraint instead
/** T must be a supertype of String! **/
<T> void parameterizedMethod()
I have an actual API example just like that.
List<T> list = new ArrayList<>();
for(int i = 0; i < 10; i++)
{
list.add((T)new String()); //is a cast actually occurring here?
}
No, no cast is actually occurring there. If you did anything with list that forced it to be a List<T> -- such as returning it -- then that may cause ClassCastExceptions at the point where the compiler inserted the real cast.

Does ArrayList.get() return the same thing as array[]?

In Processing, I have an ArrayList of objects built from a custom class. When I use the .get() function to return one of the objects, it seems to return the object all right -- but I can't access any of the object's variables or methods. I get the error message "[variable] cannot be resolved or is not a field." Is this a bug, or am I doing something wrong?
Here's a sample. Notice the values returned from the setup() function.
// regular array
Thing[] thinglist1 = new Thing[1];
// ArrayList array
ArrayList thinglist2 = new ArrayList<Thing>(1);
// instantiate the class
Thing thing = new Thing(12345);
// class definition
class Thing {
int var;
Thing(int i){
var = i;
thinglist1[0] = this;
thinglist2.add(this);
};
};
// run it!
void setup(){
println(thinglist1[0] == thinglist2.get(0));
// true
println(thinglist1[0].var);
// 12345
println(thinglist2.get(0).var);
// ERROR: "var cannot be resolved or is not a field"
};
You've kinda messed up your generics.
Change
ArrayList thinglist2 = new ArrayList<Thing>(1);
to:
ArrayList<Thing> thinglist2 = new ArrayList<Thing>(1);
Because you didn't specify a type, what you really had was:
ArrayList<? extends Object> thinglist2 = new ArrayList<Thing>(1);
So when you retrieved an item from it using get, it was typed as Object rather than your Thing
Edit to add: The reason for this is legacy; when generics were introduced things were put in place for backward compatibility. Unfortunately that creates situations like this which is confusing to someone new to Java.
You'd prob expect a compiler warning or error, but Java silently changes that non-generic-typed ArrayList into "Arraylist that contains something that extends Object" ... which is anything (except a primitive), because all objects implicitly extend Object
In the last line you must cast return value from get function to the array of object.
System.out.println(((Thing[])thinglist2.get(0))[0].var);

Categories

Resources