Goto statements raised angst because they were seen as the underlying cause of bad programming. Most believed that they accelerated the degree of 'spaghetti'-ness of the code. They allowed programmers to construct obscenely complicated logic that was nearly impossible for a human to follow, and consequently could never be fixed or expanded.
Getting rid of goto statements, or at lest discouraging their abuse was a very good idea.
Then along came pointers in C. The language was so accommodating, that the programmers were allowed to write all sorts of things that didn't work properly. You'd think we'd learn our lessons about abusing specific aspects of a language, but with each new generation of coders there seems to need to go back towards making a mess again.
So we went though a prolonged period of having hanging pointers and strange crashes. It was, some people felt, a step forward to get away from C and start using some of the newer languages. In time there were excellent tools written to find hanging pointer problems, but mostly the had came along to late to be effective.
The intent in Java was to protect the programmers from themselves. At least that was the original idea. In spite of that, there are at least two great popular messes in Java right now that are the continuing source of bad programming problems.
The first is threads. Few programmers really understand them, so much of the multi-threaded code is exceptionally poor and prone to glitches. When modern applications occasionally act a little funny, chances are your crossing some type of threading bug. By now I've seen so many, in so many well known applications, that it safe to say that multi-threading is probably the single worst language feature since C pointers.
The result is that we end up with lots of people shooting themselves in the foot in ways that are incredibly hard to detect and nearly impossible to reproduce. Bad code that's destined to never get found or fixed.
Another great mess are the anonymous callback functions in Java. Mixing that with some good olde async calls can make for a wonderful pile of spaghetti.
Syntactically, it is really ugly because you end up dropping a stray semi-colon into the middle of a code block. Semantically it is ugly because you stuffing declarations into places where it should be running code. And structurally it is truly hideous because the flow of control is bouncing all over the place into a multitude of little functions. Nothing taste more like spaghetti than being able to fragment the logic into a huge number of different locations. It is the power of a "goto" all over again.
We not too clever in Computer Science. We keep reinventing new ways to make bad code. You'd think by now we would have developed an attitude close to that of Niklaus Wirth, whose aim I think, with languages like Pascal, Module-2 and Oberon is to tightly control the code so that there is less room for badly written software. What is the point of having access to this huge computer tool if you keep opening holes around it to shoot yourself in the foot. Shouldn't we be using that computational power to help us find our problems before we release them? Do we really like pain that much that we have to do it all ourselves and not take advantage of our tools?