int x = 5;, we would say that x is
not an object.
double[] A = new double[10];, we would say that
A is an object.
Foo is a class (think "struct" for the moment)
and we have the declaration
Foo f = new Foo();, we would say
that f is an object.
Normally, if we use the term "object" we are referring to
class objects.
| primitive values | array objects | class objects |
int i = 7; double x = 4.32; char c = 'q'; boolean b = i*x > 28.5; int j = (int)x; byte b = (byte)255; |
int[] A = new int[2]; A[0] = 5; A[1] = 7; String[] B = new String[3]; B[0] = "hi"; B[1] = "bye"; B[2] = "wow"; |
String s1 = "Groot"; String s2 = "I am" + s1; Scanner s = new Scanner(System.in); String s3 = s.next(); String s4 = s3.toLowerCase(); String iAmEmpty = new String(); |
Important! Now, here's the truly important thing to know: values of a primitive type are basically the same as in C++; picture a box with the value written in the box. Assignment copies the contents of the right-hand side box into the left-hand side box. Function arguments are passed by value, just as they are by default in C++. Variables referring to array-objects and class-objects work just like pointers in C++ (though they are called references in Java); picture a little box with an arrow pointing to the box that actually has values written inside.
public class Ex1
{
public static void foo(int a, int[] b, String c)
{
// do something here!
}
public static void main(String[] args)
{
int i = 4, j;
int[] A = {3,5,7}, B;
String s = "hey", t;
j = i;
B = A;
t = s;
foo(i,A,s);
}
} |
![]() |
This depicts the state of affairs at the // do something here!
comment. Notice that we always have pass-by-value
semantics in Java, but that passing a reference by value
means getting a reference that points to the same thing.
This is exactly the same as the behavior we saw with
pointers in C++!
|
Because variables of array-object or class-object type are references, they behave differently than the primimitive types when they are not initialized. For example:
int k; String s;The variable
k is an uninitialized int ... it's an
int, we just can't rely on it having any specific value.
The variable s, however, is a reference that
doesn't refer to any object. We call this a null-reference, and
it's just like a NULL-pointer. The literal for the
null-reference is simply null.
Thus, you can make a test like
if (s != null) ...or set a reference deliberately to null like:
s = null;
Primitive types: boolean char byte short int long float double
byte type?
Well, Java's char type is actually 16-bits, because
Java uses Unicode rather than ASCII, so that strings can contain
characters from many different languages. While that's pretty
transparent to us as programmers, it leaves us without the
char-byte equivalence we rely upon in C/C++. Therefore, Java has
a type byte that is an 8-bit signed integer —
just like C/C++'s char type.
double, but with less
precision). Operators are the same as well: +,-,*,/,%. All the
rules
about integer division/modulus still apply.
So what happens when this is run?
int i = 13;
int j = 7;
int k = 2;
double m = 0.0;
System.out.println("values: " + (i%j) + " " + (j/k) + " " + (j+m)/k);
boolean a = true;
boolean b = false;
System.out.println("values: " + (a+b));
System.out.println("values: " + (a||a) + " " + (a || b) + " " + (b || b) + " "
+ (a&&a) + " " + (a && b) + " " + (b && b));
char x = 'y';
char y = 'x';
System.out.println("values: " + x + " " + y + " " + (x+y));
What would happen if we took out the () inside the printlns?
Widening conversions are converting a type to a "larger" type, like int to double. There are 19 possible:
These can be done automatically:
int i = 3;
double d = i;
the int 3 is widened to a double. Widening usually doesn't lose information.
Narrowing can lose information and precision, and requires a "cast". There are 22 Narrowings
float fmin = Float.NEGATIVE_INFINITY;
float fmax = Float.POSITIVE_INFINITY;
System.out.println("long: " + (long)fmin + ".." + (long)fmax);
System.out.println("int: " + (int)fmin + ".." + (int)fmax);
System.out.println("short: " + (short)fmin + ".." + (short)fmax);
System.out.println("char: " + (int)(char)fmin + ".." + (int)(char)fmax);
System.out.println("byte: " + (byte)fmin + ".." + (byte)fmax);
Everything can be converted to a string. That's what is happening when you do this: "STRING " + 3; There are a number of other conversions that we'll talk about later on.
When do these conversions happen?
public static double foo(double argh){
return (argh*argh)/(argh-1);
}
public static void main(String[] args){
int i = 3;
System.out.println("foo: " + foo(i));
}
One important difference is you can NOT treat a string like an array. stringVariable[1]= 'p'; will cause your compiler to yell at you. However, Java Strings DO have a function called .charAt(int), which will retrieve a copy of the character at a certain index in the string. Additionally, Strings have a large number of other useful functions, including .length(), indexOf(), .substring(), .toUpperCase() and many, many more. It's worth taking a look in your book or online to see all the things Strings can do.
As with C++, the '+' operator with Strings does concatenation - i.e. glues the strings together.
String s = "he", t = "llo"; String w = s + t; // now w is "hello"What's crucially different, however, is that an expression of the form String + value is evaluated by converting value into a String and then doing concatenation. Thus,
"r" + 3 results in
"r3". The + operator is left-associative, so
"r" + 3 + 2 gives "r32", but 3 + 2 + "r"
gives "5r".
One last important point about strings: they
are immutable, meaning they can;'t be modified.
So, if we have String s = "hello world";
and we want to capitalize the first letter, we can't simply
modify the first letter of the String object s refers to.
Instead, we have to make a new String that looks like what we
want.
s = s.substring(0,1).toUpperCase() + s.substring(1);This makes a new string "h" from s, then makes a new string "H" from the first, then makes a new string "ello world" from s, then makes a new string by concatenation, then assigns s to point to the result. What happens to the original s, "h", "H" and "ello world" you might ask? They are orphaned! They sit out there on the heap and are no longer referred-to/pointed-to by anything. In C++ this would be a disaster, but not in Java. Java has automatic garbage collection, which means the virtual machine automatically detects and reclaims orphaned memory! That's a huge burden off your shoulders as a programmer!
x to be a reference to an array
of objects of type Foo with the syntax:
Foo[] x; However, as with C++, this x
doesn't have an actual array to point to yet. To allocated an
array of n objects of type Foo and
set x to point to it, we make the assignment:
x = new Foo[n];
For example:
int[] joe; ← this declares joe as an array reference joe = new int[10]; ← this allocates (on the heap) an array of 10 ints and sets joe to point to itOf course, we can do both at once like this:
int[] joe = new int[10];It's the same for other types:
boolean[] aBoolArray = new boolean[10];Java arrays are, for the most part, like C++'s dynamic arrays. However, you can initialize them with syntax reminiscent of C++'s static array initializers, like this:
String[] aStringArray = { "array", "of", "String" };
... which is nice.
Access is done as with C++. Note, however, that we can always use .length to arrive at the length of an array. This is not a function, as with Strings, but is an attribute of the array:
int[] ia = new int[101];
for (int i = 0; i < ia.length; i++)
ia[i] = i;
int sum = 0;
for (int i = 0; i < ia.length; i++)
sum += ia[i];
System.out.println(sum);
If we change one of the < to a <=, our C++ experience tells us to expect either a Segmentation Fault or a silent bit of weirdness, which is kind of horrible. Instead we get a message about an ArrayIndexOutOfBoundsException, and an indication of which line caused it to happen, which seems strangely wordy, but much, much more useful.
Multidimensional arrays work just the same, but are easier to allocate:
int[][] anArr = new int[10][9]; //An array with 10 rows and 9 columns
for (int i = 0; i < anArr.length; i++) //anArr.length is 10, just like C++
for (int j = 0; j < anArr[i].length; j++) //anArr[i].length is 9, just like C++
anArr[i][j]=0;