In the below code, EX1 and EX 2 prov the homogeneous theory but in EX3 it holds multiple types values. So then, how we can say arrays are homogeneous? What is the exact theory behind this?
public class Test {
public static void main(String[] args) {
// Ex 1
int [] intArr = new int[5];
intArr[0] = 1;
intArr[1] = 2;
// Ex 2
int [] intArr2 = new int[5];
intArr2[0] = 1;
intArr2[1] = "ss";
// Ex 3
Object [] objArr = new Object[5];
objArr[0] = 1;
objArr[1] = "ss";
objArr[3] = new Object();
}
}
There are a two concepts here: inheritance and auto-boxing
Inheritance -
A String inherits from Object and hence is an Object. This means that String gets all methods and properties defined in the Object class automatically at compile time. It is an Object plus additional stuff that is specific to the String. However, it can be viewed by Java as an Object because it is an Object. When it is added to the array, it is added as an Object, not as a String. That is because the Array is defined as an Array of objects.
char a = "ss".charAt(1); // Legal as charAt(..) is a method in the String class
Object [] objArr = new Object[5];
objArr[1] = "ss";
objArr[1].charAt(1); // Not legal because charAt(..) method is not defined for Object
See Oracle Tutorial.
Auto-Boxing -
Java performs a shortcut known as auto-boxing to a automatically convert primitives to a special set of wrapper Classes all of which inherit from Object. Hence, because of auto-boxing and inheritance, assigning a number to an Object will convert that number to an Object as well.
Hence, everything added to the array was added as an Object. It is true that the objects in the array may be classes that inherited from Object. However, as far as the array is concerned, they are of type Object. Even so, if you were to pull it out of the array and cast it as an Integer, you could do so. It still carries the Integer information with it but that information in not available without a cast. From the array's point of view, it is only an Object.
See Oracle Tutorial.
Related
I came to know from this stackoverflow question that the code
test1[] t = new test1[2];
in the following program
class test1{
public int n;
void set(int n1){
n=n1;
}
}
class test{
public static void main(String arg[]){
test1[] t = new test1[2];
for(int i=0;i<2;i++)
t[i] = new test1();
t[0].set(12);
t[1].set(13);
for(int i=0;i<2;i++)
System.out.println(t[i].n);
}
}
is needed to initialize the array of objects of the class test1, and trying to access the objects without the code :
for(int i=0;i<2;i++)
t[i] = new test1();
throws the following error :
Exception in thread "main" java.lang.NullPointerException
at test.main(test1.java:12)
But I also tried to execute the following program:
class test{
public static void main(String args[]){
Integer[] n = new Integer[2];
n[0] = 9;
n[1] = 18;
for(int i=0;i<2;i++){
byte b = n[i].byteValue();
System.out.println(b);
}
}
seems to work without any error although I have not initialized the array of object of the Integer class, using the code :
for(int i=0;i<2;i++)
n[i] = new Integer();
How is it that, the array of objects of the Integer class and that of the class created by me differ in this case.
Is it that the objects for the class that I create requires initialization and the objects for the class Integer does not require initialization. Am I getting it right ? I just wanted to know how the classes that users create and classes that already exist differ.
I have not initialized the array of object of the Integer class, using the code :
Yes, you did initialize the contents of the array n. Just like any reference array, an Integer[] is initialized with all nulls.
However, you did supply values:
n[0] = 9;
n[1] = 18;
You just didn't use new, because Java will autobox the int literals into Integer objects. You are storing the Integer objects corresponding to 9 and 18.
It doesn't matter if the objects are for classes that you create or not. It matters whether you are using a "wrapper" type for Java's primitive values. You can always have Java autobox primitive values into wrapper types, e.g. int to Integer.
The JLS, Section 5.1.7, lists all possible boxing conversions:
From type boolean to type Boolean
From type byte to type Byte
From type short to type Short
From type char to type Character
From type int to type Integer
From type long to type Long
From type float to type Float
From type double to type Double
From the null type to the null type
I am having difficulty understanding what an Object[] is. Is it an Array that keeps Objects ? For example what happens when we do this :
int a = 5;
String b = "Hi";
Object[] c = { a, b };
Did I just create an object with properties a and b added to it ? Or did I get an Object Array in which a and b was counted as objects and elements of this c the object array ?
Thanks.
Actually you created an array of objects derived from Object (which is true for all object in Java), now containing an Integer (created by autoboxing) on position 0, and a String on position 1.
Java is not dynamically typed so you cannot add properties on the fly like in javascript (without reflection). Btw. in java you dont call them properties, but instance-members/fields or methods if its a function, which are defined in classes (but you usually work with instances which is constructed from a class). So Object is a class and Object obj = new Object(); obj is an instance
The notation ClassName[] always notates an array of type ClassName, so
Object[]
notates an array of objects. And
String[]
an array that can only contain Strings.
You can initialize an array with
Object[] objArr = new Object[3];
which creates a new empty array which can hold 3 elements. Or you can directly set the elements by
Object[] objArr = {"elem1","elem2","elem3"};
which creates an array with 3 elements (elem1-3). So therefore:
System.out.println(objArr[0]); //"elem1"
System.out.println(objArr[1]); //"elem2"
System.out.println(objArr[2]); //"elem3"
System.out.println(objArr[3]); // ArrayIndexOutOfBoundsException
Because you used Objectas a type you can set practically anything to the array since any class automatically inherits from Object
Object[] objArr = {"elem1",2.34,new Date()};
System.out.println(objArr[0]); //"elem1"
System.out.println(objArr[1]); //2.34
System.out.println(objArr[2]); //11.05.2014
2.34 is a double, so a primitive, but since 1.4 java autoboxes every primitive into its Object pendant (so Double), thats why it works. Note that usually in a statically typed language you dont want to do that this way since you lose alle the advantages of statical type checks, so better define your types and use them.
Did I just create an object with properties a and b added to it ?
No. Those are elements. Properties != Elements.
did I get an Object Array in which a and b was counted as objects and elements of this c the object array ?
Little wrong. Counted as elements, which are objects.
Object[] c = { a, b }; // a is Integer and b is String
When you write the above line, that means you created an array Objects with elements a and b in it. You can refer the array with c
Is it an Array that keeps Objects ?
To be precise, it's an Object that contains references to other Objects.
All objects in Java are created and live on the heap until the garbage collector reclaims them. References point to those memory locations and give your program access.
The example you gave uses two immutable objects. The real fun would happen if you chose a mutable object and added it to your array.
On executing the program it will print,
5
Hi
on iterating the array. that shows the Object array consist of a of Integer and b of String.
It's an array of objects. You've auto-boxed a from a primitive int into an Integer and added that, and String b to the Object array. Remember all Objects extend Object. Try casting the Objects to their subclass types and maybe this will help you understand what's going on. E.G.
int a2 = (Integer) c[0];
String b2 = (String) c[1];
Object[] is an array of object references. From your code, imagine you did this:
int a = 5;
String b = "Hi";
Object o1 = a; // Autoboxes to java.lang.Integer
Object o2 = b;
Pretty similar to:
int a = 5;
String b = "Hi";
Object[] c = new Object[2];
c[0] = a;
c[1] = b;
... right? Which is exactly what your code above does, in a more shorthand way. So, you create an array where each element holds a reference to an Object.
Objects are superclasses of every non-primitive in Java. In your code:
int a = 5; // <- int is a primitive
String b = "Hi"; // <- String is a subclass of Object
Object[] c = { a, b };
c wants to have an array of Objects, and since a is an int, autoboxing occurs (this means that the compiler makes the int an Integer-object). You can compare it to the following code (this is basically what the compiler does behind the scenes).
int a = 5; // <- int is a primitive
String b = "Hi"; // <- String is a subclass of Object
Object[] c = { new Integer(a), b }; // <- int is autoboxed to it's container-class Integer
As I mentioned, Objects are the superclass of every non-primive in Java. So let's compare your code to the following:
I have three classes:
class C{ } // Just compare this with Object
class B extends C{ } // Compare this with String
class A extends C{ } // Compare this with Integer
// translating your code to:
A a = new A();
B b = new B();
C[] c = { a, b };
The left side is the reference type and the right side is the object type.
// List is the reference type, ArrayList is the object type
List<String> list = new ArrayList<String>(); // (or List<String> list = new ArrayList<>(); in Java 7+)
// With the C, B and A classes above:
// C is the reference type, A is the object type
C myClass = new A();
So I have this class, and I want to method that takes in an int, and creates a new array of that size. If I
declare
newArray<Object<int,int>> array1 = new newArray<Object<int,int>>(10);
This would create an array of size 10.
I've tried doing
public class newArray<O>
{
private O[] array;
public newArray(int newArraySize)
{
newArray<O>[] = new newArray<O>[newArraySize];
}
}
but I get an " Cannot create a generic array of newArray " error.
Unfortunately, you can't create a generic array. This is due to the way generics are implemented in Java, which is through type erasure. In effect, all generic types are "erased" to their bounding type (usually Object) before compilation, so all the compiler sees are Object instead of T or E or O. The erasure process generates automatic casts to ensure that the program would still work as intended.
This means that you can't do:
new O() (this gets erased to new Object(), which the compiler has no idea what to do with)
new O[] (this gets erased to new Object(), which again isn't helpful to the compiler)
What you can do is casting:
array = (O[]) new Object[size];
And in fact, that's how it's done in Java's Collections framework. You'll get an "unchecked" warning, as the compiler can't prove that this conversion is safe, but there really is no other option.
Also, few things I want to point out about your question, that you may or may not know already:
You can't use primitives as type parameters
Object has no type parameters
newArray<O>[] = new newArray<O>[newArraySize]; should really be array = new newArray<O>[newArraySize];. You already declared the array you wanted to use. So use it!
Looks like you're implementing your own ArrayList, in fact. If you are, good luck! If you aren't, you should really be using the existing implementation, unless you need some special behavior that you can't get otherwise...
You are almost there.
Take a look at the following code for an example on how to initialize, populate, and print an array.
import java.util.*;
public class Test
{
public static void main(String[] args)
{
// define the array
List<Integer> array1 = new ArrayList<Integer>(10);
// initialize the array with some value. In this case, the Integer "200"
// note that the array doesn't have a hard limit of 10 as define above. You can change the following value to 20 and it will still work
for (int i = 0; i < 10; i++)
{
array1.add(i, 200);
}
// print the array
System.out.println(array1);
}
}
Does this help?
ArrayList<Integer[][]> r = new ArrayList<Integer[][]>(10);
// You could replace the above list with a custom list
Integer[][] ob = new Integer[1][2];
ob[0][0] = 10;
ob[0][1] = 20;
r.add(ob);
for(Integer[][] o : r)
for(Integer[] o1 : o)
for(Integer o2 : o1)
System.out.println(o2);
And the output is:
10
20
What is the difference between these two lines?
int pInt = 500;
and
Integer wInt = new Integer(pInt);
Or
Integer wInt = new Integer(500);
None.
That's the exact same thing. In the first case you just have a supplementary variable.
Note that with autoboxing you rarely need to have both an int and an Integer variables. So for most cases this would be enough :
int pInt = 500;
The main case where the Integer would be useful is to distinguish the case where the variable is not known (ie null) :
Integer i = null; // possible
int i = null; // not possible because only Object variables can be null
But don't keep two variables, one is enough.
In Java, an instance of a primitve class holds the actual value of the instance, but instance of a wrapper class holds a reference to the object. i.e. The address of the place where the object would be found.
When you write a program with this line:
Integer integer = 500;
The compiler changes it to this:
Integer integer = new Integer(500);
This process is called autoboxing. That is automatically putting a primitive-instance in a "box" of Integer. Hence, output of the following program:
public class PrimitiveToObject {
public static void main(String[] args) {
printClassName(1);
printClassName(1L);
printClassName((char)1);
}
public static void printClassName(Object object){
System.out.println(object.getClass());
}
}
is this:
class java.lang.Integer
class java.lang.Long
class java.lang.Character
Also this:
int i = integer;
changes into this:
int i = integer.intValue();
This is called unboxing.
As you can see above, the dot operator(.) is used on the variable named integer but not on i. That is: a wrapper's object can be dereferenced, but not a primitive instance.
Boxing and unboxing may slow down the program a little bit. Hence, to a newbie, wrappers may look like added burden, but they are not so. Wrappers are used at places where the object needs to be a reference type. eg: Map<Integer,String>map=new HashMap<Integer,String>(); is a valid statement, but Map<int,String>map=new HashMap<int,String>(); is not a valid statement.
Another typical case where wrapper is very useful: In MySQL, NULL is a valid entry for a column of INT type. But in Java, int cannot have a null value, Integer can. This is because in SQL NULL symbolises Not Available. So if you are using JDBC to insert integer values in a MySQL table, a null in your java program will help in inserting NULL in the MySQL table.
A wrapper class can also be useful in a case similar or anologous to this:
Boolean decision; // Using wrapper for boolean.
if("YES".equalsIgnoreCase(consent))
decision = Boolean.TRUE; // In favour
else if("NO".equalsIgnoreCase(consent))
decision = Boolean.FALSE; // Not in favour
else if("CAN'T SAY".equalsIgnoreCase(consent))
decision = null; // Undecided
For starters
int pInt = 500; , here pInt is not an object whereas in
Integer wInt = new Integer(500);
wInt is an reference
This is also a reason why java is not pure Object Oriented Language. Because everything is not object with java.
Wrapper class will have a box in that box it will cover the primitive data types there are 8 primitive data types namely byte,int ,long ,double, float, short ,Boolean ,char these all covered in wrapper class .
to use primitive data types we use like int a;
but to use wrapper class we need to use like Integer a = new Integer(i);
The types of data are the same, but there are situations that manipulation of objects is more convenient than primitive types, like data structures, where you need more control of your data types.
For example, objects can be null and primitive types can't.
You also can't call methods in a primitive type (.compareTo(), .equals(), ...), but in wrapper classes you can.
The information below describe the types in primitive and wrapper class:
Primitive Types | Wrapper Class (Superclass = Object)
boolean - Boolean
char - Character
Primitive Types | Wrapper Class (Superclass = Number)
byte - Byte
short - Short
int - Integer
long - Long
float - Float
double - Double
To understand how the wapper classes works, consider the example below:
public final class IntWrapper {
private final int intVal;
IntWrapper(int intVal) {
this.intVal = intVal;
}
public int getInt() {
return intVal;
}
}
Now we can make an object out of our new IntWrapper class and 'box' the primitive int value 41:
int i = 41;
IntWrapper iw = new IntWrapper( i ); // box the primitive int type value into the object
i = iw.getInt(); // unbox the value from the wrapper object
My example IntWrapper class is immutable, immutable means that once its state has been initialized its state cannot be changed.
When the final keyword is applied to a class, the final class cannot be extended. In other words, a final class can never be the superclass of a subclass. A final class can be the subclass of superclass, not problem there. When a class is marked final, all of its methods are implicitly final as well.
It is important to note that when final is applied to a reference variable it does not prevent the members of the object instance from changing values.
This example is to better understanding how the wrapper classes works inside.
Next, to create Integer, Double and other wrapper classes, you can write:
Integer i = new Integer(4);
Double d = new Double(9.62);
Boolean b = new Boolean("true");
Character c = new Character('M');
To get the encapsulated number into wrapper objects, you can write:
long l = i.longValue();
double e = i.doubleValue();
float f = d.floatValue();
short s = d.shortValue();
Each wrapper class include special methods to convert between primitive type to wrapper objects, that represent not number values:
boolean bo = b.booleanValue();
char ch = c.charValue();
Up to Java 5 version, the creation of objects from wrapper classes had to be in the syntaxes like above, but to simplify these operations, mainly related to insertion of values in the data structures offered in Java collections (that only accept objects), now exists the autoboxing or boxing and autounboxing or unboxing options.
The autoboxing or boxing allows you to insert a primitive value to reference of equivalent wrapper types or Object type:
// Same result of Double d = new Double(-2.75);
Double objD = -2.75;
// Same result of Object objI = new Integer(13);
Object objI = 13;
The autounboxing or unboxing allows you to insert a wrapper object into a variable of primitive type, converting automatically between equivalent types:
// Same result of double vd = objD.doubleValue();
double vd = objD;
// Same result of int vi = objI.intValue();
int vi = objI;
The most important practical difference I've seen is Integer is way more slower to initialize and do calculations with, than int. I would avoid Integer unless necessary.
int x = 20_000_000;// 20 millions
for (int i = 0; i < x; i++) {
ix += 23;
}
it takes 138 ms(average over 50 trials) to complete the loop when ix is an Integer but only takes 10 ms when ix is an int
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I copy an object in Java?
How can I initialize an object (say A) in java and set its initial member values equal to a second object (say B). After initialization I want to modify the members of A without modifying the members of B. So at initialization of A I only want to copy the data of B. How is this done in a nice way??
You could implement and use clone
MyClass b = new MyClass();
MyClass a = b.clone();
Note: some classes are not Cloneable, or have broken implementations. e.g. only have a shallow copy when they should be a deep copy.
If the class is Serializable you can serialize it and deserialize it in memory. Not exactly nice but it works.
Or you could create your own "copy" constructor.
One possible solution for that would be implement clone method on your class and use clone as follows:
MyClass a = new MyClass();
MyClass b = a;
You will notice that clone() isn't really a public method, so your will need to expose it. Additionally you need to tell Java that your object is Cloneable (this is done making your class implement Cloneable). The following code ilustrate it:
public class MyClass implements Cloneable {
#Override
protected MyClass clone() throws CloneNotSupportedException {
return (MyClass)super.clone();
}
}
That all depends on the type of the members. I'll give an Example:
class A
{
public float value;
public int[] anArray;
public A(B b)
{
//primitive may be assigned directly.
this.value = b.value;
// other types different approaches:
//copy the contents of the array
this.anArray = new int[b.anArray.length];
System.arraycopy(b.anArray, 0, this.anArray, 0, b.anArray.length);
}
}
class B
{
float value;
int[] anArray;
public B(int size)
{
this.value = 3f;
this.anArray = new int[size];
for (int i = size - 1; i >= 0; i--)
{
this.anArray[i] = i * 10;
}
}
}
B b = new B(5);
A a = new A(b);
Cloning is a straightforward option for copying. If you ever want to do something where you need more control, create your own method that performs your copy exactly how you need it:
public MyType copy()
{
MyType a = new MyType();
// Initialize how you need to here, use the object this was called from if you'd like
a.property = this.property;
// etc.
return a;
}
This gives you more direct control, but takes more time to code. If clone will suit your purposes, stick to that.
EDIT: I am going to give an example based on your comments on this answer.
Let us assume we have the following types:
TypeA: has the following member variables
int number = 5; // Default value built in by constructor.
int letter = 'x'; // Value is 'a' when constructed but has been changed.
ArrayList<TypeB> list = {b1, b2, b3} // All are initialized.
TypeB: has the following member variables
double decimal = 5.32
TypeC someObject = ...
TypeC: has some stuff, but we are going to ignore it.
Now, When we want to copy TypeA, we must do the following:
Copy over the number and character directly as they are value types.
Copy over a reference to the ArrayList which contains a reference to some TypeBs.
Luckily those are easy steps.
int copyNumber = this.number;
char copyChar = this.letter;
ArrayList<TypeB> copyList = this.list;
return new TypeA(copyNumber, copyChar, copyList);
Now that assumes a particular constructor that takes those three arguments, but hopefully you get the idea.
It would get tricky if you wanted to just get values, not references to all of the TypeBs in the ArrayList. You would have to loop through the ArrayList and create new TypeBs that copied all of ITS values (double and TypeC objects as either references or values...)
In short, what you want is an easier copy to perform. Simple assignment operators copy values with primitive types and references with Objects.