public class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p == null && q == null) return true;
if(p == null  q == null) return false;
if(p.val != q.val) return false;
return true && isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
}
Simple easy to read Java solution

The first three conditionals will check the base cases, which are every case except
if(p.val == q.val)
the 'True' represents that, (it is True that p.val == q.val, because we already checked the other possibilities). I like doing this with recursive problems that require a boolean return value, the call stack would look a little like this:
true && someFunc(val) true && true && someFunc(val) true && true && true && someFunc(val) true && true && true && true && false && someFunc(val)
where the false in the last line would cause the original caller to evaluate to "false". Let me know if that makes any sense!