Matriz com linhas ilimitadas

Boa tarde, sou inciante em java, e estou criando um algoritmo para o gerenciamento de um banco. Para cada saque que o cliente fizer, eu armazeno os dados em uma matriz, e cada linha armazena os dados de cada saque. Essa matriz é estática e armazena os dados dos saques de todos os clientes. Ela armazena o código da conta, o código do saque (que é gerado automaticamente através de um método) e o valor sacado. Eu gostaria de saber se tem como eu criar uma matriz onde as linhas seriam ilimitadas, sendo criadas conforme fossem feitos novos saques, e não que ela ficasse limitada em uma quantidade de saques. Isso é possível? Obrigado pela atenção… Vou colocar aqui o que eu criei até agora… Eu pretendo fazer a mesma coisa com o saque para o depósito e a transferência, mas não criei essa parte ainda…


Cliente titular;
	private double saldo;
	private double limite;
	private double saldoTotal;
	int codigoConta;
	int codigoExtrato;
	int codigoSaque;
	int codigoDeposito;
	int codigoTransferencia;
	static int contadorCodigoConta;
	static int contadorCodigoExtrato;
	static int contadorCodigoSaque;
	static int contadorCodigoDeposito;
	static int contadorCodigoTransfrencia;
	private static String saque[][] = new String[100][3]; //Matriz que armazenas os dados dos saques. Quantidade de saques limitada em 100. Aqui que eu gostaria de saber se pudesse ser ilimitado.
	private static String deposito[][] = new String[100][3]; //Matriz que armazena os dados dos depósitos.
	private static String transferência[][] = new String[100][4]; //Matriz que armazena os dados das transferencias, só acrescendo os dados da conta de destino do valor.
	
	void novaConta() { //Gera código da conta quando criada nova conta.
		Conta.contadorCodigoConta += 1;
		this.codigoConta = Conta.contadorCodigoConta;
	}
	
	int novoExtrato() { //Gera o código do extrato quando requerido um extrato.
		Conta.contadorCodigoExtrato += 1;
		this.codigoExtrato = Conta.contadorCodigoExtrato;
		return this.codigoExtrato;
	}
	
	void novoSaque() { //Gera o código de cada saque. Inicia no código 0 por causa da posição da linha da matriz.
		this.codigoSaque = Conta.contadorCodigoSaque;
		Conta.contadorCodigoSaque += 1;
	}
	double setSaldo() {
		return this.saldo;
	}
	
	double setLimite() {
		return this.limite;
	}
	
	double setSaldoTotal() {
		this.saldoTotal = this.saldo + this.limite;
		return saldoTotal;
	}
	
	void atualizaLimite() { //Atualiza o limite de acordo com o saldo. Se o saldo for negativo, limite passa a ser 0.
		if (this.saldo > 0) {
			this.limite = 0.4551 * this.saldo;
		}
		else {
			this.limite = 0;
		}
		
	}
	
	private void deposita(Conta destino, double valor) { //Método deposita, usado pelo depósito e pela transferência.
		destino.saldo += valor;
		destino.atualizaLimite();
	}
	
	private void saca(double valor) { //Método saca, usado pelo saque e pela transferência.
		this.saldo -= valor;
		atualizaLimite();
	}
	
	void deposito(Conta destino, double valor) { //Método de depósito. Em construção.
		deposita(destino, valor);
	}
	
	void saque(double valor) { //Método de saque.
		if (valor <= setSaldoTotal()) { //Verifica o limite para validar o saque.
			novoSaque(); //Gera código de um novo saque (inicia em 0);
			saca(valor); //Saca o valor.
			saque[this.codigoSaque][0] = Integer.toString(codigoConta); //Armazena o código da conta em String.
			saque[this.codigoSaque][1] = Integer.toString(codigoSaque); //Armazena o código do saque gerado em String.
			saque[this.codigoSaque][2] = Double.toString(valor); //Armazena o valor sacado em String.
		}
		else {
			System.out.println("Saldo insuficiente para saque.");
			System.out.println("Valor máximo para saque: ... R$ " + valorMaximoSaque);
		}
	}
	
	void transferencia(Conta destino, double valor) { //Transferência. Em construção.
		System.out.println("----------------- TRANSFERÊNCIA -----------------");
		System.out.println("Conta origem: ..... " + this.codigoConta);
		System.out.println("Conta destino: .... " + destino.codigoConta);
		System.out.println("Valor: ............ " + valor);
		if (valor <= this.saldo + this.limite) {
			saca(valor);
			destino.deposita(destino, valor);
			System.out.println("Seu novo saldo: ... " + this.saldo);
		}
		else {
			System.out.println("Saldo insuficiente para transferência.");
			System.out.println("Valor máximo para transferência: ... R$ " + this.limite + this.saldo);
		}
		
	}
	
	private void infoConta() { //Método para mostrar informações da conta. Usado pelo extrato.
		System.out.println("Número da Conta Corrente: ....... " + this.codigoConta);
		System.out.println("Titular: ........................ " + titular.setNome());
		System.out.println("Código do titular: .............. " + titular.geraCodigoCliente());
		System.out.println("Saldo de Conta Corrente: ........ R$ " + setSaldo());
		System.out.println("Limite: ......................... R$ " + setLimite());
		System.out.println("Saldo Total disponível: ......... R$ " + setSaldoTotal());
	}
	
	void infoTransacoes() { //Método que mostra as transações. Por enquanto tá mostrando só os saques.
		System.out.println("------------------- TRANSAÇÕES ------------------");
		for (int cont = 0; cont <= this.codigoSaque; cont++) { //Pesquisa sequencial que busca os saques da conta na matriz saque verificando pelo código da conta.
				if (Integer.parseInt(Conta.saque[cont][0]) == this.codigoConta) { //Transforma o código da conta armazenado em String na matriz para inteiro, para verificar com o número da conta. Aqui eu tenho uma dúvida também... Tinha tentado o contrário "if (Conta.saque[cont][0] == Integer.toString(this.codigoConta);" e não comprava, pois não retornava nada escrito... Porque?
				System.out.println("* SAQUE *");
				System.out.println("Código da conta: ................ " + Conta.saque[cont][0]);
				System.out.println("Código do saque: ................ " + Conta.saque[cont][1]);
				System.out.println("Valor: .......................... R$ " + Conta.saque[cont][2]);
				}
		}
	}
	
	void extrato() {
		System.out.println("=========== EXTRATO DE CONTA CORRENTE ===========");
		System.out.println();
		System.out.println("Código do extrato: .............. " + novoExtrato());
		this.infoConta();
		System.out.println();
		this.infoTransacoes();
	}

}

Obrigado pessoal…

Para isso existe List;

ArrayList<Integer> contas = new ArrayList<Integer>()

Caso você deseje armazenar 2 valores, utilize o Map;

HashMap<Integer, Pessoa> cadastro = new HashMap<Integer, Pessoa>();

[quote=pb600]Para isso existe List;

ArrayList<Integer> contas = new ArrayList<Integer>()

Caso você deseje armazenar 2 valores, utilize o Map;

HashMap<Integer, Pessoa> cadastro = new HashMap<Integer, Pessoa>();

Só complementando.
É importante lembrar que quando se cria uma Array comum o seu tamanho não pode ser alterado.
Só para exemplificar.

byte[] array = new byte[8];

Já quando você usa o ArrayList, ele irá sempre criar uma nova linha na lista quando você adicionar algo novo.

List<Integer> contas = new ArrayList<Integer>()

O sinal está dizendo que essa lista só aceita o tipo de dado passado ali como parâmetro, no caso o Integer.
Isso é chamado de Generics, que permite restringir o tipo de dado que irá para a sua coleção no caso a lista. Caso tente adicionar um dado diferente de Integer tipo uma String irá acontecer um erro em tempo de compilação, seu codigo nem irá compilar.
Criar uma lista assim:

List contas = new ArrayList()

Tambem é possível só que nesse caso essa lista comporta todo tipo de dado que seja um object, e quando você for extrair um dado dessa listá, é obrigado fazer um casting explicito para o tipo de dado que você está extraindo. Com o uso do Generics apresentado logo assima, o casting já não é necessário pois o Java já sabe qual dado tem na lista, e dela só irá retornar um tipo de dado.
O Generics é bastante util, recomendo que leia um pouco sobre o assunto.

Muuuito obrigado pb600 e Ziru. Vou estudar um pouco sobre isso que vocês falaram e vou aplicar aqui… Muito obrigado mesmo!

Não é possível aumentar o tamanho do array, mas é possível criar um outro maior, jogar os dados do array antigo pro novo e fazer a referência do array antigo apontar pro novo. Que é ± o que as implementações de List abstraem para nós.

Então depende de cada caso. Se o intuito é deixar mais fácil, use List ou outra Collection de uma vez; se o intuito é aprender, implemetar tudo com array, pode ser interessante.