Okay. I'm going to go back to basics and give you a simple model of how this should work, rather than staring at your code.
Let's say your screen res is 1024x768. Your tiles are 256x256 -- huge tiles, I know, but we're just working on the principles here. So your screen covers 4 tiles across and 3 down.
When you first run your program, the tile you're currently focused should be at the top left of your screen (0,0). It stretches down to (256, 256) on your screen.There are two tiles directly below it, and 3 directly to the right, because of the size of your screen and your tiles. Lets assume you have no offset yet, then the tile at the top left of your screen will be tiles[0,0].
Now, lets say your whole grid is 8x6 tiles. That means it's 2 screens across by 2 down. Starting from the top left of your map, you would be able to scroll right 7 times (8 minus 1), and down 5 times (6 minus 1), before the bottom-right-most square of the map would be at the top left of your screen -- with black (empty spaace) all around it -- the empty space around your array's bottom-right-most tile, AKA tiles[7,5]. Got it?
If you scrolled up and left from here, what would happen? Well, if you coded things right, you'd see some black (empty) space, because now you're looking at regions outside your array, such as tiles[-1,-1] etc., which obviously don't exist because in Java there are no negatively-indexed arrays. (As long as you make sure you never try to reference the array with a negative number, it will behave as I've described -- you'll see black, gray or whatever your background colour is, if you scroll out-of-bounds).
Okay. Now next up what you have is a Camera. From our human point of view, the map isn't moving, but the camera is. It has an x and a y value. And unlike the array, this camera can have any index you like, even (-42, -80). These are your offsets into (or outside of!) the map. So in my original example where you first run your program, that's when the camera offset is (0,0). If you set it to (0,1), you would now have shifted your view one cell down, meaning you could no longer see tiles[0,0], but instead you would have tiles[0,1] in the top left of your screen. If you shifted your camera up instead, by setting it to (0,-1), you would see tiles[0,0] at the middle left of your screen, and black "void" above tiles[0,0] (and it's 3 neighbours to the right which are also on your screen).
So whats the relationship between Camera and background? Well, the Camera's just a marker, really. It doesn't physically move, but since everything in life is relative, it may as well be. What's really moving are your background tiles. You move the background by negative (minus one times) each of the Camera's x and y values. And that's the key. The camera simply notes the offsets and wraps the idea of a movable camera up in an easy-to-use-and-understand sort of way, but it's the map tiles, as you draw them, that actually move accordingly. And as for the map array in memory? -- That stays exactly the same, of course, since it's just a model of the world, and that doesn't change just because the view changes.
How do you prevent yourself getting an array out-of-bounds error, then, when you move your camera so far to the left that it goes off the map? Well, you just need to make sure that if your minus one times camera offset produces either a negative x or a negative y, that you DO NOT try to index into the array to determine what type of tile it is, and this what graphic to draw. In these cases, you simply do nothing. Otherwise you will Java will throw an NPE.
This should get you started. There is other stuff, like offsetting the view by one-half of screen's width and one-half of a screen's height, so that whatever coordinate you push into the camera, instead of that tile being visible at the top left of the screen, it will be visible in the centre (for example; it could be anywhere you want it but centring is the most useful). And then the smooth scrolling we mentioned. But I think the above gives you enough to chew on for now?
One last thing. Although I mention pixel sizes in this example, for now they just aren't important. What's important is only your tile offsets. Again, you should not be thinking in terms of pixels right now, that will come later when you look at smooth scrolling. The only place in your code where pixels should come in is literally where you draw your tiles on screen each render update, something like
for (y = camera.y; y < camera.y + screenHeightInTiles; y++)
for (x = camera.x; x < camera.x + screenWidthInTiles; x++)
drawTileAt(x*tileWidth, y*tileWidth); //<-- this is the only place you're working with pixels, i.e. tileHeight and tileWidth (if they're not exactly the same)