When I first heard of using var
, I didn't quite understand why we would want to use it. After all, one of Java's strengths is that it is a strongly typed language. Doesn't using var
weaken this? Not at all. In this tutorial, we will look at when we can use var
, when we can't use var
, and why programmers would want to use it in the first place. I'll also supply many examples, so let's dive in.
What is var used for?
- We can declare a variable of type
var
when the actual type of the variable can be inferred based on what it is assigned to:
- Local variables with initializers &
- Indexes in enhanced for-loops and traditional for-loops
- While you can use
var
when we are assigning the result of a method call. You may not want to where the type of the return is ambiguous. While the compiler will understand that type, this practice will make the code less readable.
When can we NOT use var?
We can not use var
if the type of values being stored in the variable cannot be inferred:
- Method returns or parameters
- Constructor returns or parameters
- Variable declarations
Why use var at all?
The introduction of var
is meant to reduce the syntax when the type of a variable can be inferred.
Many other languages have something equivalent, such as: C++, C#, Scala, and Go
Java is a strongly typed language, doesn’t using var
diminish this strength? Absolutely not, since var
can only be used when the type of the variable can be inferred.
Local Variables
Below are some examples of when you can use var
for declaring and initializing local variables.
Example 1
Since age
is being assigned to 7
, we can infer that age
is of type int
. This is the same as:
Example 2
Since brady
is being assigned to a new Dog
object, we can infer that brady
is of type Dog
. This is the same as:
Example 3
Since wordlist
is being assigned to a new ArrayList
of String
objects, we can infer that wordlist
is an ArrayList
of strings. This is the same as:
For Loops
Example 1
In this example, var
is being used to declare word
. Since we know that wordlist
is an ArrayList
of String
objects, we can infer that word
is of type String
. This is the same as:
Example 2
In this example, var
is being used to declare the step variable in the for loop. This is the same as:
Not Recommended Uses of var
The following example will work, but is not recommended. While the compiler can infer the type, the someone reading the code cannot infer the type making the code less readable.
Example 1
var brady = new Dog();
var sound = brady.bark();
In this case, it is unclear what is being returned by the method bark
. It could be:
- A
String
- A
File
containing the sound of a dog barking
- A
boolean
value that represents that the dog is barking
While the compiler knows the return type, the code is less readable without knowing the return value of bark()
.
Improper Uses of var
The following are examples of when you are not allowed to use var
.
Example 1
var wordlist;
Without initialization, the compiler is unable to infer the type of wordlist
.
Example 2
var brady = null;
Since null
can be assigned to objects of any type, the compiler is unable to infer the type of brady
.
Example 3
var[] numbers = {1, 2, 3};
We need to have the type on the right side, so we could change this to:
var numbers = new int[3];
or
var numbers = new int[] {1, 2, 3};
Example 4
public var greeting(String name) {
return "hi " + name;
}
We are unable to use var
as a return type even though the return value is clear.
Example 5
public String greeting(var name) {
return "hi " + name;
}
We are unable to use var
for the type of the parameter.
Example 6
public class Dog {
String name;
public Dog(var n) {
name = n;
}
}
We are unable to use var
for constructor parameters. The type of a parameter needs to be specified and cannot be inferred.
Example 7
public class Dog {
var name;
public Dog(String n) {
name = n;
}
}
Unable to use var
for instance variables. Since name
is not instantiated when it is declared, we can not use var
.
Using var Reminders
- The use of
var
is not required.
- Using
var
can only be done when the type can be inferred. It cannot be used every where. It can be used in the following places:
- local variables with initializers
- for loops: enhanced-for and traditional
Using var on AP CSA Free Response Questions
How does this look on the exam?
Now that we have taken a chance to understand var
outside of the AP CSA exam. Let's look at an example of how students might use this on the AP Computer Science A (AP CSA) exam.
The following are examples of how students could use var on the AP CSA Free Response Exam. You can find all of the questions here
Free Response Question 1 - Bird Feeder
This question involved a simulation of a bird feeder and requires students to do the following:
- generate random values
- use if statement
- use loops
Part A - Example Canonical Solution
public void simulateOneDay (int numBirds) {
boolean bearPresent = false;
double bear = Math.random() * 100;
if (bear <= 5) {
bearPresent = !bearPresent;
}
int birdConsumed = ((int) (Math.random() * 41) + 10) * numBirds;
if (bearPresent)
{
currentFood = 0;
}
else{
if (birdConsumed >= currentFood) {
currentFood = 0;
else {
currentFood = currentFood - birdConsumed;
}
}
There are three variable declarations in the sample solution above:
bearPresent
– is assigned to the Boolean false
. The type is unambiguous with the assignment.
bear
– is assigned to a double
from Math.random()
. You could use var
, but it can be ambiguous to use with a method return.
birdConsumed
– even though there is a method call, the typecast to an int
makes the type clear that the value being assigned is an int
.
A sample solution using var
is as follows:
public void simulateOneDay (int numBirds) {
var bearPresent = false;
double bear = Math.random() * 100;
if (bear <= 5) {
bearPresent = !bearPresent;
}
var birdConsumed = ((int) (Math.random() * 41) + 10) * numBirds;
if (bearPresent)
{
currentFood = 0;
}
else{
if (birdConsumed >= currentFood) {
currentFood = 0;
else {
currentFood = currentFood - birdConsumed;
}
}
Part B - Example Canonical Solution
public int simulateManyDays(int numBirds, int numDays) {
int count = 1;
for(int days = 1; days <= numDays; days++) {
if(currentFood == 0) {
return days;
}
simulateOneDay(numBirds);
}
return numDays;
}
There are two variables declared in the sample solution above:
count
- Since the variable is being assigned to 1
, it is unambiguous and is a good place to use var
.
days
- The for loop counter days
can be declared using var
.
This sample solution using var is as follows:
public int simulateManyDays(int numBirds, int numDays) {
var count = 1;
for(var days = 1; days <= numDays; days++) {
if(currentFood == 0) {
return days;
}
simulateOneDay(numBirds);
}
return numDays;
}
Free Response Question 2 - Scoreboard
In this free response question, students are asked to write a class for a scoreboard with two teams. Students will need to:
- declare instance variables
- write constructors
- write methods
- use if statements
The following is a sample solution:
public class Scoreboard {
private String team1;
private String team2;
private String activeTeam;
private int team1Score;
private int team2Score;
public Scoreboard(String t1, String t2) {
team1 = t1;
team2 = t2;
activeTeam = team1;
team1Score = 0;
team2Score = 0;
}
public void recordPlay(int points) {
if (points == 0) {
activeTeam = (team1.equals(activeTeam)) ? team2 : team1;
} else {
if (team1.equals(activeTeam)) {
team1Score += points;
} else {
team2Score += points;
}
}
}
public String getScore() {
String retVal = team1Score + " – " + team2Score + " – " ;
retVal += (team1.equals(activeTeam)) ? team1 : team2;
return retVal;
}
}
In this solution, we have many data types where students might be tempted to use var
. However, you cannot use var
for the following:
- instance variables
- constructor or method parameters
- method return types
If a student were to use var
in these places, they will likely lose points.
There is only one place in the solution above where a student could use var
if they wanted to do so. In the getScore
method the String
variable, retVal
, is declared and assigned the concatenation of team scores and a string hyphen. Since the concatenation of strings with int
values creates a String
, it is unambiguous what type we are using and var
can be used appropriately.
A sample solution using var is as follows:
public class Scoreboard {
private String team1;
private String team2;
private String activeTeam;
private int team1Score;
private int team2Score;
public Scoreboard(String t1, String t2) {
team1 = t1;
team2 = t2;
activeTeam = team1;
team1Score = 0;
team2Score = 0;
}
public void recordPlay(int points) {
if (points == 0) {
activeTeam = (team1.equals(activeTeam)) ? team2 : team1;
} else {
if (team1.equals(activeTeam)) {
team1Score += points;
} else {
team2Score += points;
}
}
}
public String getScore() {
var retVal = team1Score + " – " + team2Score + " – " ;
retVal += (team1.equals(activeTeam)) ? team1 : team2;
return retVal;
}
}
NOTE: In this solution we have used the ternary conditional operator. This operator is not a part of the AP Java Subset. You do not need to teach this operator.
Learn more on the Ternary Conditional Operator.
Free Response Question 3 - WordList
In this free response students will need to:
- loop over a list
- access adjacent elements of a list
- use string methods
- add values to a list
- create a new list
Part A - Sample Canonical Solution
In part A of this free response question, students are asked to determine if the previous word is a substring of the next word.
public boolean isWordChain() {
for (int index = 0; index < wordlist.size() – 1; index++) {
String nextWord = wordlist.get(index + 1);
String currentWord = wordlist.get(index);
if(nextWord.indexOf(previous) == -1) {
return false;
}
}
return true;
}
In this solution, there are three variables being declared:
index
- the for loop counter index
can be declared with var
nextWord
and currentWord
- students could use var
to declare these variables, but this would be considered less readable, since the value these are being assigned comes from a method call. In this case, we are using common method calls and will likely know that wordlist
stores String
values, but it is still considered less than desirable to use it in these two cases.
A sample solution using var
is as follows:
public boolean isWordChain() {
for (var index = 0; index < wordlist.size() – 1; index++) {
String nextWord = wordlist.get(index + 1);
String currentWord = wordlist.get(index);
if(nextWord.indexOf(previous) == -1) {
return false;
}
}
return true;
}
Part B - Sample Canonical Solution
In part B, students need to make a list of all word that have the target word at the beginning, but with the beginning of the word is removed.
public ArrayList<String> createList(String target) {
ArrayList<String> retList = new ArrayList<String> ();
for (String word : wordList) {
if (word.indexOf(target) == 0) {
retList.add(word.substring(target.length()));
}
}
return retList;
}
In this solution, var
could be used in two places:
retList
- a new ArrayList
that is able to store string values
word
- used in the enhanced-for loop to store the values in wordList
, which are strings
A sample solution using var
is as follows:
public ArrayList<String> createList(String target) {
var retList = new ArrayList<String> ();
for (var word : wordList) {
if (word.indexOf(target) == 0) {
retList.add(word.substring(target.length()));
}
}
return retList;
}
Free Response Question 4 - GridPath
In this free response students will need to:
- access elements in a 2D array
- use a provided class
- use conditionals and loops
Part A - Sample Canonical Solution
In this part, students need to return the smaller of two values, either below or to the right if they exist.
public Location getNextLoc(int row, int col) {
int numRows = grid.length;
int numCols = grid[0].length;
if (row + 1 == numRows)
return new Location(row, col + 1);
if (col + 1 == numCols)
return new Location(row + 1, col);
int below = grid[row + 1][col];
int right = grid[row][col + 1];
return (below < right) ? new Location(row + 1, col) : new Location(row, col + 1);
}
In this solution, we have declared four variables:
numRows
and numCols
- The value assigned to numRows
and numCols
is from the constant length. Since this is really common, it is most likely readable to use var
in these cases. However, if there is any doubt about the readability, you will want to use the type and be clear.
below
and right
- The values assigned to below
and right
are what is being stored in grid
and is not ambiguous.
A sample solution with var
is as follows:
public Location getNextLoc(int row, int col) {
var numRows = grid.length;
var numCols = grid[0].length;
if (row + 1 == numRows)
return new Location(row, col + 1);
if (col + 1 == numCols)
return new Location(row + 1, col);
var below = grid[row + 1][col];
var right = grid[row][col + 1];
return (below < right) ? new Location(row + 1, col) : new Location(row, col + 1);
}
NOTE: In this solution we have used the ternary conditional operator. This operator is not a part of the AP Java Subset. You do not need to teach this operator.
Learn more on the Ternary Conditional Operator
Part B - Sample Canonical Solution
In this solution, students are summing the values along a path using the return value from getNextLocation
.
public int sumPath(int row, int col) {
int total = 0;
while (row < grid.length – 1 || col < grid[0].length – 1) {
total += grid[row][col];
Location next = getNextLocation(row, col);
row = next.getRow();
col = next.getCol();
}
return total;
}
In this solution, we have two variables that are being declared and assigned values:
total
- which is unambiguous being assigned to 0
.
next
- assigned a returned type from a method call. This method is a local method and would be easy to find, however, it is still considered less readable to use var
in this case.
A sample solution with var
is as follows:
public int sumPath(int row, int col) {
var total = 0;
while (row < grid.length – 1 || col < grid[0].length – 1) {
total += grid[row][col];
Location next = getNextLocation(row, col);
row = next.getRow();
col = next.getCol();
}
return total;
}
Final Thoughts on Using var with AP CSA
Use of var and the AP CSA Free Response Questions
- Using
var
is OUTSIDE the AP CSA Java Subset
- Students can write correct solutions using
var
- Using
var
can be used in any FRQ. Students need to be careful using it with FRQ 2, since they cannot use it with instance variables, parameters, and return types.
Scoring and Teaching
- Student solutions that use correct Java syntax can earn full credit for their solution
- Questions are written with an in AP Java subset solution in mind
- Students should be encouraged to write solutions within the AP Java Subset
- Students could lose points if they use
var
and do not assign the variable to a value that is not unambiguous.
Resources
Experimenting with var in the Java Playground