1

Let's say I have 3 classes.

  • Class A (extends Activity)
    Class B
    Class C (extends View)

A creates a B object that holds a Bitmap. A also invalidates C. C's onDraw draws a Bitmap to its Canvas.

How do I draw the Bitmap that B holds without creating another Bitmap object in C? Note it is important for me to keep the same "class structure."

Here is the pseudo code. You can see this puts 2 Bitmap objects in memory. Thanks!

public class A extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        B b = new B();
        C c = (C) findViewById(R.id.c);

        c.passTheBitmap(b.bitmap);
        c.postInvalidate();
    }       
}

public class B {
    public Bitmap bitmap;
    public B(){
        bitmap = BitmapFactory.decodeResource(ActivityAContext.getResources(), R.drawable.fooBitmap);
    }
}

public class C extends View {
    public Bitmap bitmap;

    public C(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public passTheBitmap(Bitmap b) {
        bitmap = b;
    }
    @Override
    public void onDraw(Canvas canvas) {
        if (bitmap != null) {
            canvas.drawBitmap(bitmap, 0, 0, null);
        }
    }
}
Carl Manaster
  • 39,912
  • 17
  • 102
  • 155
user432209
  • 20,007
  • 10
  • 56
  • 75
  • How does this put 2 `Bitmap`s in memory? Java uses pass-by-reference, and according to your code above, there's only one `new` call and consequently only one `Bitmap` created. There should be two *references* to it, one held by C and one by A. Are you running into problems? – Cheezmeister Feb 20 '11 at 21:33
  • Actually Java _does not_ use pass by reference which is what prompted this question. – user432209 Feb 20 '11 at 21:44
  • 1
    @Cheezmeister, @user432209: you're both wrong. Java uses pass-by-value for primitives (int, char, etc) but pass-by-reference for objects. *That's* why the confusion. – Mac Feb 20 '11 at 21:56
  • @Mac my bad; I accidentally deleted the "usually" XD – Cheezmeister Feb 20 '11 at 22:04
  • 1
    @Mac - Actually Java passes everything by value including references. The confusion arises because there are no 'object values' i.e. you can only obtain references to instances of classes. – Lee Feb 20 '11 at 22:31
  • @Lee That's true, but still doesn't make it "pass by value"--would you expect references to be passed by reference? That's silly! Objects are passed by reference. Primitives (unless wrapped in `Integer`, etc.) aren't. Mac's right on the money. – Cheezmeister Feb 20 '11 at 23:39
  • @Cheezmeister - There is a difference between passing an object by reference and passing an object reference by value. A variable passed by reference is an alias for the real value which means a function is able to modify such an argument in the caller. This is not possible in Java since everything is passed by value, however C# does indeed allow you to pass references by reference using the ref keyword. You can understand Java parameter passing without knowing the difference but some languages (e.g. C#, C++) do require it. – Lee Feb 21 '11 at 00:26
  • @Lee: I might agree that that's technically the case, but from the point of observable semantics of the language it makes more sense to remember that objects are pass-by-reference and primitives are pass-by-value, since that "explains" why the rules about making changes for each are different (with regard to the observable changes in a method caller). – Mac Feb 21 '11 at 01:33
  • @Mac - The 'observable semantics' are that Java passes parameters by value - that is why you cannot write a function which swaps the values of its arguments in the language. The rules for making changes to arguments are the same for both references and primitive types, namely that assignments made to method arguments are not visible in the caller. I think it makes more sense to remember that variables in Java are either primitives or references (not objects) and that these are always passed by value. – Lee Feb 21 '11 at 11:31

2 Answers2

3

Well, by having the instance variable declared in C, you're not exactly duplicating the Bitmap object in C. You're just having another reference to the original Bitmap object that gets created in the constructor of B.

adarshr
  • 61,315
  • 23
  • 138
  • 167
  • 1
    Once again my poor understanding of Java is _ONLY_ pass by value comes back to bite me in the ass. I just tested it and it looks like you are correct. – user432209 Feb 20 '11 at 21:40
  • @user432209 Jave ONLY passes by value for primitives ... you are correct, but there is a big exception to the rule. Any class will pass by Reference. Therefore, if you passed a class object of type B to another area and affected its data ... the original reference would be changed as well. – Matthew Cox Feb 20 '11 at 21:56
1

I assume you think that the following line:

c.passTheBitmap(b.bitmap);

Would cause b.bitmap to get copied. It doesn't, so long as b.bitmap is not a primitive.

In your code, the only way for there to be a second copy is if you use new to create a new object intentionally.

E.g. in class C

public passTheBitmap(Bitmap b) {
    bitmap = new Bitmap(b);
}

If you do as you have done:

public passTheBitmap(Bitmap b) {
    bitmap = b;
}

... then A.b.bitmap and C.bitmap will reference the same object in memory.

If this was C++, then you have a valid concern - but in Java, what you are doing does not make a copy of the object being passed.

HTH

bguiz
  • 27,371
  • 47
  • 154
  • 243