(Note, it is probably easier to read this post on the blog, and not in the version that is emailed to you.)
Consider a simple Java class, Foo.

This class has multiple scopes. The outermost scope defines a field, x, that is initialized with the value 5. This declaration puts x in the scope of all subsequent code, including all method definitions.

Now, within the method fun, we see that a parameter x is declared as well. The scope of this particular instance of x is more limited.

This is an example of nested scopes. It is no different, in many regards, from our usage of with in the language of our interpreter. In fact, it is identical: the nested use of x completely shadows the declaration of x at the top level of the class. (You can read a bit more about lexical scope on the Wikipedia.)
As it happens, Java gives us a special way of breaking out of our lexical scope.

Through the use of this, we can can refer to this.x, which allows us to "break out" of the current scope, and refer to a binding of x that is at the top level of the class. Without this keyword, we would have no way of breaking the lexical scope of either fun or main, and as a result, x would be completely shadowed.
From lexical scope to De Bruijn indices
In response to James's question from class today: the concept of scope has nothing to do with whether Scheme is object-oriented, or whether Java is functional (like Scheme, ML, Haskell, or Erlang) or procedural (like Pascal and C). As a language designer and implementer—as one who studies languages—we should be concerned with the syntax and semantics of languages (and perhaps more importantly, the semantics).
In the case of scope, we see that nested scopes in Java behave the same as they do in our interpreter for WAE. That said, our interpreter does not have a notion of this. Java lets us reach out of the current scope and refer to a variable that was defined in an outer scope. We can implement this, if we want.
In the environment-passing interpreter (the interpreter of deferred substitutions), you could add a new production to the language:
WAE := {outer <id>}
Instead of resolving to the value of the first value of <id> in the current environment, we could define outer to force the <id> to resolve to the next value in the environment. That would be similar, unless we had more than two levels of nesting... if that was the case, simply adding an outer to our language would not solve the problem fully.
Perhaps we could instead use an index:
WAE := {ndx <id> <num>}
With the ndx form, I could write code like this:
(with (x 3)
(with (x 5)
(with (x 8)
(- x (+ (ndx x -1) (ndx x -2))))))
In the semantics of WAEN (adding in the ndx form), I expect this to evaluate to zero: it should be the same as saying (- 8 (+ 3 5)).
Now, I have a way of referring to a particular variable name and at a particular level of lexical scope. The reference {ndx x -2} would mean the binding for x two levels of scope out from where I am now. (Confused yet? You should be. This strikes me as a confusing way to write code.)
In doing this, I've practically invented De Bruijn indices. You can read about those either in the course text, or you can read about them on the Wikipedia. Either way, I would claim that this does not make our code clearer (we have the ability to give different variables different names... why refer to the same variable over and over by a number?). However, this can be a very useful transformation to help guarantee uniqueness when you're writing, say, an interpreter or compiler.
NOTE ABOUT WIKIPEDIA:
I'm referring to the wikipedia because it is convenient. If you want a more definitive treatment of these ideas, you should go into the library and pick up any of a number of texts on programming languages. We are studying these concepts through their implementation; if you would like additional readings to support your implementation efforts, I'm happy to recommend some from the library in Alden Hall.

