I apologize for my trivial and probably silly question, but I am a bit confused as to when to use the "this" prefix when using a method or accessing something.
For example, if we look at #4
here:
http://apcentral.collegeboard.com/apc/public/repository/ap_frq_computerscience_12.pdf
And we look at the solutions here:
http://apcentral.collegeboard.com/apc/public/repository/ap12_computer_science_a_q4.pdf
We see that one solution to part a) is
public int countWhitePixels() {
int whitePixelCount = 0;
for (int[] row : this.pixelValues) {
for (int pv : row) {
if (pv == this.WHITE) {
whitePixelCount++;
}
}
}
return whitePixelCount;
}
while another solution is
public int countWhitePixels() {
int whitePixelCount = 0;
for (int row = 0; row < pixelValues.length; row++) {
for (int col = 0; col < pixelValues[0].length; col++) {
if (pixelValues[row][col] == WHITE) {
whitePixelCount++;
}
}
}
return whitePixelCount;
}
Here is my question. Why is it that they use the "this." prefix when accessing pixelValues and even WHITE in the first solution, but not in the second? I thought "this" was implicit, so am I correct in saying "this." is NOT necessary at all for the first solution?
Thank you SO much for your help :)
With this, you explicitly refer to the object instance where you are. You can only do it in instance methods or initializer blocks, but you cannot do this in static methods or class initializer blocks.
When you need this?
Only in cases when a same-named variable (local variable or method parameter) is hiding the declaration. For example:
private int bar;
public void setBar(int bar) {
this.bar = bar;
}
Here the method parameter is hiding the instance property.
When coders used to use it?
To improve readability, it is a common practice that the programmers prepend the this. qualifier before accessing an instance property. E.g.:
public int getBar() {
return this.bar;
// return bar; // <-- this is correct, too
}
From The Java™ Tutorials
Using this with a Field
The most common reason for using the this keyword is because a field is shadowed by a method or constructor parameter.
For example, the Point class was written like this
public class Point {
public int x = 0;
public int y = 0;
//constructor
public Point(int a, int b) {
x = a;
y = b;
}
}
but it could have been written like this:
public class Point {
public int x = 0;
public int y = 0;
//constructor
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
When the name of a method parameter is the same as one of your class data member; then, to refer to the data member, you have to put this. before it. For example, in the function setA():
public void setA(int a)
{
this.a = a;
}
Since both the data member and the papameter of the method is named a, to refer to the data member, you have to use this.a. In other cases, it's not required.
And, in your case, I don't think it's necessary to use the this, though there is no harm to use it.
this refer to the instance of the class itself. Example:
private String name, car;
public class Car(String name, String color)
{
this.name = name;
this.color = color;
}
Related
#Data
public class MyData {
private long a;
private long b;
private long c;
}
if we want to update all the field of a,b,c, then code could be like below:
MyData d;
...
d.setA(d.getA()+2);
d.setB(d.getB()+5);
d.setC(d.getAC()+8);
in other language, we may write code like:
d.a += 2;
d.b += 5;
d.c += 8;
Any graceful way to do update with this mode in java?
The other answers are all technically correct, but to give some conceptual thoughts: what you are thinking of/asking for is called Uniform Access Principle - the idea that reading and writing to a field follows the same syntax. Respectively the idea that x.y and x.y() can actually mean the same thing.
And for good or bad, Java does not support that concept on the syntactical level, and lombok doesn't help here either.
If you want to assign a value to a field, you either need an explicit setter (or maybe increment) method, or you need to make the field public.
End of story.
While you could make your fields public:
public class MyData {
public long a;
public long b;
public long c;
}
and then just
MyData d;
//...
d.a += 2;
d.b += 5;
d.c += 8;
a better approach would be to introduce increment methods:
public class MyData {
private long a;
private long b;
private long c;
public void incrementA(long x){
a += x;
}
public long incrementAndGetA(long x){
a += x;
return a;
}
public void incrementB(long x){/*...*/}
public long incrementAndGetB(long x){/*...*/}
}
and then...
MyData d;
//...
d.incrementA(2);
long bb = d.incrementAndGetB(4);
This approach will maintain encapsulation.
Obviously you can add decrement methods (or just use negative values).
you can write a function about that.
#Data
public class MyData {
private long a;
private long b;
private long c;
void add(long number1, long number2, long number3){
a += number1;
b += number2;
c += number3;
}
}
You can also use negative numbers for extraction.
You can simply create a dedicated method:
public class MyData {
private long a;
...
// use setter to set value
public void setA(long value){
this.a = value;
}
// add to current value
public void addToA(long value){
this.a += value;
}
...
}
You could also make those fields public, it comes to your choice.
But methods can do more things, like validate input values. It's also a way of encapsulating values inside of the class, and let smart methods to modify their values.
You can also modify Lombok builder to have a custom setter. You can find a thread on this here
#Builder
class MyData {
....
public static class MyDataBuilder {
public MyDataBuilder a(long value) {
this.a = value;
return this;
}
}
}
You could provide an access method
public void manipulateX(Function<Integer, Integer> manipulator) {
x = manipulator.apply (x);
}
You can then call that with mc.manipulateX(i -> i+ 2).
I have a function like that
Class Return_two{
public static void main(String args[]){
int b=0;// Declare a variable
int a []= new int[3];// Declare an array [both are return at the end of the user define function fun()]
Return_two r=new Return_two();
int result_store= r.fun(a,b);//where should I store the result meaning is it a normal variable or an array where I store the result?
}
public int [] fun (int[] array,int var)//may be this is not a good Return type to returning an array with a variable so what will be change in return type?
{
for(int counter=0;counter <array.length;counter++)
{ var=var+counter;
}
return( array,var);// Here how could I return this two value in main function?
}
}
Now, here lies my question. I want to return an array with a variable as I written above.But as I know one can return a array or a variable but not both. Or one can return one or more variable make those variable as a array element. But how can one return an array with an variable in main function?
If you want to create multiple values, wrap them in an object.
(I'm not able to come up with a meaningful name from what you have posted)
class Result {
private int[] a;
private int b;
public Result(int[] a, int b) {
this.a = a;
this.b = b;
}
//Getters for the instance variables
public int[] getA() {
return a;
}
public int getB() {
return b;
}
}
At the end of fun
return new Result(array, var);
Some best practices:
Don't declare variable names with same name as a parameter (a in fun)
In the above Result class, better to create copies on the array a to avoid mutations outside the class.
If possible, don't use arrays and use a List (this would give you a lot of flexibility)
EDIT:
Your caller will look like
Return_two r=new Return_two();
Result result = r.fun(a, b);
result.getA();//Do whatever you want to do with the array
result.getB();//Do whatever you want to do with that variable
With your current version of the (modified) code, why do you want to return the array since it is same as what you pass to the fun method? Returning only the computed var will work for you (and hence the return type can simply be int).
You can also achieve what you do in fun in one line
return (array.length * (array.length - 1)) / 2;
Wrap these properties into a object, say
Public class FunModel
{
public int[] a;
public int b;
}
then you can return an instance of `FunModel`.
Or
you can use `Tuples`
------------------
Futher Explanation
------------------
The return type here should be a model.
This model should have all that you want to return as properties.
You can return this model from your method.
public class FunModel
{
public int[] a;
public int b;
public FunModel(int[] a, int b) {
this.a = a;
this.b = b;
}
}
And the method should return a instance of this model.
public class ReturnTwo {
public static void main(String args[]){
int b=0;
int a []= new int[3];
ReturnTwo returnTwo = new ReturnTwo();
FunModel funModel = returnTwo.fun(a,b);
//other processing
}
public FunModel fun (int[] array,int tempVar)
{
FunModel temp = new FunModel(array,tempVar);
for(int counter=0;counter <array.length;counter++)
{
temp.b = temp.b + counter;
}
return temp;// you return the model with different properties
}
}
We got the following exercice in our last exam, and I don't understand the right answers except the 1st one.
Here is it:
public class Gran {
private int x;
public Gran() { this.x = 68; }
public int age() { this.x = this.x+1; return this.x; }
#Override
public String toString() { return "Gran " + age(); }
}
public class Dad extends Gran {
private int x;
public Dad() { this.x = 41; }
#Override
public String toString() { return "Dad " + age(); }
}
public class Bro extends Dad {
private int x;
public Bro() { this.x = 21; }
#Override
public int age() { System.out.print("Bro "); return x; }
}
public class Sis extends Dad {
private int x;
public Sis() { this.x = 17; }
#Override
public int age() { System.out.print("Sis "); return super.age() - x; }
#Override
public String toString() { return "Sis " + super.toString(); }
}
What would be the correct print-outs if we call this:
Gran[] family = new Gran[] {new Gran(), new Dad(), new Bro(), new Sis()};
for (Gran member : family) System.out.println(member.toString());
It would be really helpful for me, if you tell me the logic behind the right answers.. I got really confused when I checked them!
You should check out the spec.
Especially Example 8.4.8.1-1. Overriding:
class Point {
int x = 0, y = 0;
void move(int dx, int dy) { x += dx; y += dy; }
}
class SlowPoint extends Point {
int xLimit, yLimit;
void move(int dx, int dy) {
super.move(limit(dx, xLimit), limit(dy, yLimit));
}
static int limit(int d, int limit) {
return d > limit ? limit : d < -limit ? -limit : d;
}
}
The caption says:
Here, the class SlowPoint overrides the declarations of method move of class Point with its own move method, which limits the distance that the point can move on each invocation of the method. When the move method is invoked for an instance of class SlowPoint, the overriding definition in class SlowPoint will always be called, even if the reference to the SlowPoint object is taken from a variable whose type is Point.
So with that in consideration, lets look at your example.
The hierarchy is:
Dad is a Gran
Bro is a Dad
Sis is a Dad
The declared type of all of the objects is Gran because of the line Gran[] family = new Gran[] {new Gran(), new Dad(), new Bro(), new Sis()}; That is the same as saying that the reference to each of the objects in the array are taken from a variable whose type is Gran.
Now you will call toString() on each of the elements in the family array. The first is Gran.toString(). When that object was created its x variable was initialized to 68. So the Gran.toString() method will build a String that is first "Gran" then call the age() method which increments x by one then returns the value of x which is 69 at this point. The + operator implicitly creates a new String that coerces the int to a String giving a String "Gran 69".
Next Dad.toString is very similar to Gran. Notice that it starts with the String "Dad" then calls age() which is inherited from Gran. So the output should be "Dad 69". The trick here is that the x variable is private scope, so the x in Dad is a different x then in Gran. That is the same for all of the classes.
For Bro, this class is a Dad, and Dad is a Gran. There is no overridden toString here so Dad.toString() gets used. That makes a String "Dad" then calls Bro.age() this prints "Bro" then returns the x from Bro to create a new String "Dad 21". The line is will look like "Bro Dad 21" because the print of "Bro" happens before the print of "Dad 21".
As for Sis this one is the toughest one. You should take everything from above and convince your self of how Overriding and scoping works. Good luck! I hope this helps.
Not to sure why the integers lowRange and highRange are not going between these classes.
package guessnumber;
public class GuessNumber
{
static public int computerGenedNumber;
static public int lowRange;
static public int highRange;
static public int playerGuess;
public static void main(String[] args)
{
Input.range(lowRange, highRange);
Rand.number(lowRange, highRange, computerGenedNumber);
Input.guess();
Give.result();
}
}
Next Class:
package guessnumber;
import javax.swing.JOptionPane;
class Input
{
public static void range(int lowRange, int highRange)
{
String rawUserInput;
rawUserInput = JOptionPane.showInputDialog("Please enter the range you wish to guess. (EX: 1-10)", "1-10");
for(int i = 0; i < rawUserInput.length(); i++)
{
if(rawUserInput.charAt(i) == '-')
{
lowRange = Integer.parseInt(rawUserInput.substring(0, i));
highRange = Integer.parseInt(rawUserInput.substring(i + 1, rawUserInput.length()));
}
}
}
static void guess()
{
}
}
And the last relevant one:
package guessnumber;
class Rand
{
static public void number(int lowRange, int highRange, int computerGenedNumber)
{
computerGenedNumber = (int)(Math.random() * (highRange - lowRange) + lowRange);
}
}
The rest of the classes are currently blank so I don't think I need to put them here too.
Here is a simplified piece of code which reproduce your problem, and make sure you understand why it is causing problem and the solution:
class Foo {
public static void square(int a, int result) {
result = a*a;
}
}
class Bar {
public static void main(String[] args) {
int a=2;
int result = 0;
Foo.square(a, result);
System.out.println("result " + result);
}
}
This should be fundamental understanding of Java. Checkout what is the meaning of "pass-by-value"
In brief, the parameter passed in the method is a copy of the argument. Therefore when you are changing the parameter in your method, you are just changing another piece of data, and your change is not reflected to caller.
One way to fix is to change the method and return your result, which looks like:
class Foo {
public static int square(int a) {
return a*a;
}
}
class Bar {
public static void main(String[] args) {
int a=2;
int result = 0;
result = Foo.square(a);
System.out.println("result " + result);
}
}
Another common solution is to pass in a "holder object" as the result. Although the object reference is passed by value, that copy of object reference is still pointing to the same object as caller. I won't go too deep into this as it is less common and you should be able to get the proper way doing so once you have better understanding on how value (including object reference) is passed around.
Parameters are passed "by value" in Java. What that means is that when you call
input.range(lowRange, highRange);
it gives the current values of those variables to input.range, but it doesn't give input.range a way to modify them. In the range method:
public static void range(int lowRange, int highRange)
the parameters lowRange and highRange (which have no connection with the variables in GuessNumber, even though the names are the same) are copies of what you pass in. When you assign lowRange = ... in the method, it changes the copy but has no effect at all on the lowRange and highRange in GuessNumber.
You need to write a range method that returns two values. This needs a little bit of work, but I'd write a Range class that has low and high members, and then change your method to
public static Range range()
That method would have to create a new Range object. I think it's OK for low and high to be public members of Range:
class Range {
public int low;
public int high;
public Range(int low, int high) {
this.low = low;
this.high = high;
}
}
Normally, public data in a class is a bad thing, but for a class whose only purpose is to let a method return multiple values, it's OK in my opinion.
Is there a short hand for defining the access modifiers of a classes fields and methods? More in a C++ style, I've searched but keep coming up with sites explaining what the purpose of each modifier is rather than a short hand.
public class myNum {
public int getNum() { return 0; }
public void setNum(int n) { int num = n; }
private int num;
private String value;
}
Could become
public class myNum {
public:
int getNum() { return 0; }
void setNum(int n) { int num = n; }
private:
int num;
String value;
}
For methods nope.
For variables you could try
public int n1,n2,n3..n;
private int n1,n2,n3..n;
But as you can see it can become messy quickly.
And even then, it doesn't allow for different types under one access modifier.
But really nope.
Although there is no short for defining methods, Eclipse can automatically generate getter and setter methods for you.