[MUSIC].
Now that we've seen how basic data types
are represented in Java, let's turn our
attention to the differences between
pointers and references be pointers in C
and references in Java.
We're going to take a look at that in
much more detail than we have so far.
And then we're also going to look at how
we organized the code for our objects in
Java.
Where do we find the methods associated
with each of the objects?
Pointers to fields in C we've seen
before, just in the last video actually.
and we've seen that the common construct
is to have a pointer to a struct
de-reference it add an offset to a
particular field.
And this is such a common situation of
referencing a field in an object to, to
which we have a pointer to a struct to
which we have a pointer.
That we have a shorthand in C, r->a.
Okay?
Which encapsulates that de-reference
there.
In Java, since all variables are
references to objects we don't have to
worry about that explicit de-reference.
Instead we always de-reference by
default, so we can use a simpler
notation, just r.a to refer to a field
within an object.
Alright?
But the thing to remember is that what's
actually going on here, is we are taking
the reference or pointer to the object
going to to that location, adding the
offset, and finding that field that way.
Let's take a look at how we do casting in
C, and contrast that to what we do in
what we can do in Java.
this is an example of code from a memory
allocation program similar to the, to the
things that we've been talking about in
the previous section.
And uh, [COUGH] what we're going to do
here is take a pointer to a block of
memory.
we're going to cast it as a simple
pointer a byte pointer.
add in offset of number of bytes.
this will point us to a new location in
memory.
And then recast that as, of, a, a
structive type block info.
Now the reason we do this, is this would
be a case, for example, we have a block
of memory.
And we want to break it into two blocks,
because we want to allocate one to
something, and have the remaining block
left over.
so remember that our block definitions
included a couple of a few variables.
the first one in integer to represent the
size and the tags of the block.
And then two pointers to the next and
previous blocks in memory.
So the way this ends up looking in in our
memory, is we started off with a pointer
tool block that had those three fields at
the front.
Alright?
The two pointers and the size and tag.
And we've now offset that by some number
of bytes x and created a new area in
memory.
That we're going to interpret as a as a
BlockInfo struct.
this is equi-, the casting is equivalent
to putting a lens over the memory, and
saying, look at this memory at this
location.
We are going to view that as a BlockInfo.
so that means we will interpret the bits
in memory in the first four bytes as the
size in tag, and the next four bytes as
the next pointer, and the next four bytes
as the previous pointer.
It's purely a reinterpretation of whats
is in memory.
And then of course we have to make sure
to put the right values there, the right
bits there to really be those pointers in
that size.
Okay, but we can do this to any region of
memory, and cast it into any struct we
want.
All we're doing is instructing the system
to view that memory in that way.
To look at it through that lens.
In Java on the other hand we can only
have pointers or references to objects.
We cannot just point to an arbitrary part
of memory.
So in, in this case I want to show an
example of a, of a, object hierarchy.
We started off with our main object.
We defined the parent object, and then
two sub-classes of that called sister and
brother.
Okay?
this code fragment here shows things that
are legal and illegal in Java.
the ones that are bad are shown in red.
but let's take a look at the beginning of
this code.
We've just defined three objects here,
one of type parent, one of type sister,
and one of type brother using the new
construct, and assigned them to a
variable of that type.
Pretty straight forward, okay.
Now let's take a look at our first cast.
We've created a new object called sister,
but put it into a pointer or a reference
to an object of type parent.
And that's okay.
Why is that okay?
Well, because sister inherits everything
from parent.
So it has all of parents feels and
methods so we can still use all those
things if we refer to the object as a
parent.
So it can, we can get away with that.
as an example if we went in the other
direction, if we had created a new
parent, and try to put it into a variable
of type sister, we have a problem.
Because sister has things that parent
doesn't have.
So when we try to cast that parent as
sister, we're missing some things.
What are we missing?
Well, at the very least we're missing
this variable hers that is expected to be
in a sister object.
Parent didn't have that.
Parent only had address.
also there might be some methods that go
along with the, with the object sister,
that we wouldn't be inheriting either.
So, that is the wrong direction to be
able to do a cast.
let's take a look at another example,
just above this one.
If we create a new object called brother,
try to cast that as a sister, that
doesn't work either.
And the reason in this case is, of
course, that brother also has a different
variable called his, that we don't know
where to put if we move it to the type
sister.
so not only is it missing hers but, it
has this other thing his, that sister
doesn't know what to deal with what to do
with.
Okay.
let's take a look at yet another one.
here you'll notice that we've taken our,
our Parent object tried to cast it as
Brother, and assigned it to a Brother
variable.
well that's not going to work either
because Brother that Parent object does
not contain all the elements of Brother.
It's missing the variable his in this
case.
Here's one that does work.
If we take a Parent object, cast it as
Sister, and then assign it to another
variable of type Sister.
Why does that one work?
Well, this one turns out to work because
this original object, p2, started out as
something of type Sister.
You'll notice that p2 was assigned p1.
And p1 was originally an object of type
Sister, that was cast as a Parent.
But it started it's life as an object of
type Sister.
So that it has everything a Sister needs,
a Sister object needs.
And so that for, therefore, that cast
works out.
So you can see things can get pretty
elaborate in Java but the basic idea is
that, to be able to do a cast the objects
have to be compatible.
They have to have the same variables in
both types, and the same methods
available so that they can be converted.
Let's take a look at objects in Java in a
little bit more detail.
We're going to run through this example
for a couple of slides here.
we've defined the class called Point.
It has two fields x and y coordinates.
It has a constructor, a function that is
called, or a method that is called
whenever we create a new object of this
type.
And what this one does is just initialize
that those coordinates at the 0.
It also has a method called samePlace,
which takes one argument another point.
And compares the x-coordinates and
y-coordinates, and sees that they're the
same logically adding them together.
When we create a new one of these Points,
this is what it would look like in our
code, we would say new Point object.
And this would cause a memory allocation
to find a place to create this object.
Namely a place to store these two
variables that it's going to need.
and it's going to return a reference to
this new location in memory, this new
object.
And then run the point constructor code
on that object.
that will cause those variables to be
initialized, and then that reference will
be stored in the variable newPoint, which
is of type Point.
So these are compatible.
So, let's review that again.
Whene, when we call new, what's happened
is we've allocated space for the data
field, in this case x and y.
But we've also done one other thing.
Here's x and y, those two doubles that we
needed.
But we've also allocated a pointer at the
beginning of the object.
To what's called a v table or virtual
table.
The v table is shared across the v table
pointer is the same for all the objects
of this class, all the points we might
create.
What it does is it points to another
region in memory, where we've stored the
pointers to the code we need for this
type of object.
In this case, there were two pieces of
code, two methods.
One was the constructor.
So we need a pointer to the constructor
code, and then samePlace.
We need a pointer to the code for that
method.
You'll notice that this is using a level
of indirection, actually two levels.
inside of the object that we've
allocated, we've left a pointer so that
we can get to the table of pointers to
the code.
That's one level of indirection.
Then when we go to that location in
memory, we'll find another pointer
another level of indirection, to the code
for the constructor, to the code from
samePlace.
And by convention, we always put the
pointer by the constructor first.
'Kay?
Once we're done with the object if we
don't need it any more in our code, and
lose all references to it.
Our garbage collection routines will find
it, find this place in memory, and say
doesn't, nothing seems to be referencing
it, we can reclaim this space, so we can
use it for other things.
And it will take back the space that had
been allocated for the object.
However, the space allocated for the v
table will continue to reside in memory,
because we might create a new point
sometime later.
This space remember, is not reclaimed for
the object.
That's a space that is allocated once,
for every object of this type.
They will all be pointing to the same
vtable.
Alright, next step let's say we created
this new point.
We've we have a place in memory for its x
and y variables and we have a vtable
pointer.
And now what we're going to do is call
this object constructor, that piece of,
that first method, that piece of code
that is going to run on to initialize
this object.
To do that, what we're going to do is
call the function constructor with a
single argument, which is going to be the
pointer to the object we've just
allocated in memory.
Okay?
which contain those, that contains those
two fields.
The Constructor code is going to run with
a pointer to this location.
So it will know that x is the very next
element, and that y is the one after
that.
And the compiler will set things up so
that those offsets are appropriately
calculated, and we can put the 0 values
in those two locations.
Now, where do the, where does the code
for the other methods go?
how do we find that?
Well, methods in Java are just functions,
as in C, but as you've noticed from the
previous slide, there's an argument
that's implicit.
Although we had defined constructor
without any arguments, the constructor
without any arguments, we did give it an
argument which was the newly allocated
space in memory.
This pointer is always refered to by the
name "this" in Java, that's a built in
keyword that says we're talking about the
reference to the current object.
Alright?
So, all of our methods really have this
as the first argument.
So the, the methods samePlace, which was
defined with a single argument p.
Really has two arguments, this and P.
so, this two pointers, point to those two
objects in in memory.
And if we had equivalent C code, it would
look like this.
we would follow this pointer to the
element x, the p pointer to the element
x, compare those two.
Do the same thing for the y's, and then
do the logical and.
Okay, so this is how we find the
variables.
And, the way we go about finding the code
is through the vtable Pointer.
How do we subclass an object?
Well, here you'll notice I've created a
new class called PtSubClass, that extends
Point.
It has a couple of different things from
Point.
One, it has a new element called
aNewField.
it also overrides the samePlace method
that we had previously defined for
points.
And, it has a totally new method called
sayHi.
So where does this new new element go,
this new integer, aNewField?
And where does the pointer to the two
other methods the code for the two
methods go.
How do we find those?
Alright?
So, what we're going to is just add these
fields and pointers on to the ends of the
object in memory, and to the end of the
vtable.
So let's take a look at what the, the map
in memory is going to look like.
Our new object is going to look just like
Point, except that it has an extra nth at
the end.
So when we allocate space for this
object, we need a little bit more space
to also be able to store aNewField.
The reason we pack it on at the end, is
that if we ever want to cast this as a
Point, we don't have to worry about the
offsets being different than they were
before.
so that x and y are still in the same
relative positions.
The vtable for this object is going to be
different than the v.table for the
previous object.
this vtable has three elements, not two,
because we have a Constructor, we have
samePlace, but we also have sayHi.
Now, where do we point to?
Well, Constructor is just going to
inherit the previous Constructor.
We didn't change that at all.
So, this is going to be a pointer to the
same region of code, the same routine
that we had for Point.
samePlace, though, is going to point to
this new code that we're using to
override the old version of samePlace.
And sayHi will of course point to a
totally different area.
So, we've tacked on a new field at the
end of the object definition, extra space
and memory for that.
we have a new vtable for Point subclass.
It is not the same vtable as Point,
because this has different methods
associated with it.
however, we are re-using, the code for
the Constructor by pointing to the same,
procedure in memory.
samePlace points to a new piece of code,
of, for this new samePlace and, of
course, we have a pointer for the new
code for sayHi.
Wyszukiwarka
Podobne podstrony:
Language Teaching Approaches and Methods02 Hearts And BonesMKULTRA Materials and Methods02 Procedure?lls and Returns02 Modeling and Design of a Micromechanical Phase Shifting Gate Optical ModulatorW42 03Petrus Bonus A form and method of perfecting base metals2006 02 Menus and Choices Creating a Multimedia Center with Mpeg Menu System V202 Performance and FragmentationSwami Krishnananda Self Realisation Its Meaning and MethodSHSpec 034 6108C04 Methodology of Auditing Not doingness and OcclusionLama Zopa Rinpoche Direct and Unmistaken MethodMEPCB1 Cross reference tables between old and new regulations of MARPOL Annex I2005 02 All on Board Kontact with Imap Based Calendar and Address ManagementInstalling and Repairing Windows NTServer 02MEPCB1 Cross reference tables between old and new regulations of MARPOL Annex I11 Theoretical Methods for Analyzing Volume Sources and Volume Conductors2005 02 Ready for Press Templates and Pdfs in Scribuswięcej podobnych podstron