A Quick Foreword
Learn By Doing: Knowledge vs Know-How
There's a huge difference knowledge and know-how. It's a common mistake for new learners to think that because they can "understand" a program as they read it, they actually understand the reasoning for the program being written the way it is.
And the only way to get to that second part is to practice. Sit down, open a text editor, a command line, and get down to it.
It's likely (and expected) that at this stage your ability to comprehend how several complex software components interact with one another is limited. And it's actually a good thing, as it forces you to start from the basics. Don't jump the gun and move at the right pace: start with small exercises for small tasks.
To be honest I've never been convinced that starting to learn programming with Java is the way to go (I used to teach programming for a living in university, and still do occasionally private tuition). It is in itself too complex to get you started, and most Java books will appear quite daunting. Nevertheless, it surely can be done (at least for some areas of that global knowledge we expect from programmerS), as long as you restrict yourself to learning step by step.
Books
As you're set on Java, and if you need a decent Java book, I'd recommend:
- Thinking in Java. It's OK, though now slightly outdated.
- The Java Tutorial. It's not exactly the best learner's companion, but a great reference to keep at hand, as it covers all the basics and provides examples. The Learning the Java Language Trail should probably be on your reading list, though I'd think it can be daunting for complete beginners as it introduces concepts that may be hard to grasp at first.
- Effective Java. It's not a great book for learning, but also an awesome reference you should have at hand for later. Not to read in one sitting, but in bite-sized chunks.
I'm only mentioning this as I don't know what you use in class. There's a tons of other books. Some are good. Some will cripple students for years.
Your Study Process
The Basic Workflow
From now on, I'd advise you to follow this 2-step process for all the exercises and code samples you've seen in class:
- read and study
- read the exercises
- make sure you understood them
- code
- close the book
- sit down in front of a computer with that code editor and command line
- attempt to rewrite the program by yourself
In case of Failure
If you fail and feel like you need to take a peek at the book, your failure is likely to be either:
- (most likely) that you didn't actually understand the solution,
- (less likely) that you've forgotten how a particular bit of the solution looks like: syntax, API use, ...
The first cause is likely to be what you face the most often. The second one is anecdotal. Both are addressed by recurrent practice.
Every time you fail at implementing one of these early examples, look at the book again, then close it again. Don't code while looking at the book. I'd even advise that you delete your entire solution and start over. The repetition is an annoying but important part of the learning process.
Do not take this lightly. Every time you feel the urge to tell yourself "yeah, ok, I know this" or "I'm 90% there, it's almost as good as done" and want to skip to another section, fight that urge back and start over. It's very difficult to have the honesty to admit to yourself that you didn't fully understand a concept.
Side note: I consider it a great disservice that most school programs now attempt to "kickstart" programming courses by dumbing things down too much and providing tooling that's too advanced for students: the goal is not to make your life miserable or for you too learn by heart things that later in your career will be automated by your tools and that you'll sometimes even barely remember. It's to teach you all the bits that float around.
In Case of Success: Go Beyond!
If you succeed at implementing your exercise, don't necessarily jump directly to the next one. Try to see what you can do to improve that one. Can you change the output that was requested? Add a small feature? An option? Try to, as you are now in that fun zone where you're passed the main difficulty, and these self-imposed tiny requirements are more likely to keep your spirits up a bit.
Don't go too far though: you don't go from printing the alphabet and reversing it to suddenly making it appear on a diagonal on the screen with a gradient of colors. Take small steps. Learning is a long and iterative process, and you need to approach problems with increasing levels of difficulty (for instance, see how I usually think of explaining recursion).
It's Just Learning - A Comparison
Your problem is actually not related to programming at all. It's the same problem thousands of people encounter when they try to learn maths.
If you give them a problem, they don't see how to work their way to the solution. However, if you write down the solution for them, most will understand it and think "darn, that was so simple!". Yet you'll give them a similar problem with different measures and hypotheses and they'll fail to solve it: they didn't understand the logic behind it, and they need practice to be able to do it themselves.
Note that this is a common problem with maths, but in my opinion you see it in tons of other fields where there's some logic required: learning solfege, language grammar, physics, etc... And it's not down to a "natural" ability to understand these things: it just comes down to practice (be it in that area, or in others that lead the individual to grasp concepts in this field more easily).
There's no reason you can't learn to write code. You just jave to keep trying until you reach that "ah AH!" / Eureka moment. Then move on to the next, harder, problem.
These may help as well (later):