grid.length and grid[0].length are not calls, but fetches of values from a field in an array object, I assume. Moreover, because these are native objects, I assume the bytecode compiler is really good at dealing with them efficiently.
I don't know that grid.length is going to be any less efficient than assigning it somewhere to a field in the underlying object (whatever object all these methods sit in) and then fetching it from that field.
grid[0].length is a bit less efficient because you have one more level of pointer indirection than if you just have a field in the underlying object. But it's such a common thing in java code for two-dimensional arrays that it wouldn't surprise me if the bytecode compiler had some special case optimization for it.
Moreover, if you were to assign the two dimensions to fields in the underlying object, say numRows and numCols, then you would have to make sure that if some method in the class ever changes what grid points to, it also updates numRows and numCols. I could easily see bugs due to forgetting to do this. It seems better stylistically to just keep all this data encapsulated in grid.
Now, what does bother me in the code are the repeated calls to getRow() and getCol() methods. Maybe these are just getters that the bytecode compiler will optimize away into field fetches, but it just hurts me to see repeated calls, and if someone revises the Location code (which we are not provided with?) in a way that makes getRow() and getCol() more expensive, the code will suddenly get unexpectedly less efficient.
I am even more bothered by getNextLoc() where we have two expensive heap allocations (with consequent garbage collections) for Location objects even though in any execution path only one of the two Location objects gets used. There are multiple ways to optimize this to use only one heap allocation. The easiest is probably to have an if-else-if ladder, executing col++ or row++ as needed, and ending with return new Location(row,col).