O colega camilolopes já fez um, mas como eu também tinha um, vou colocar ai pro pessoal, qto mais melhor não é? Comentei cada passo pra ficar bem fácil de entender… espero ajudar flw 
class StringsStringBuilderStringBuffer {
public static void main(String[] args) {
Strings();
StringBuffers();
}
//esse método cobre tudo sobre Strings
//Strings são imutáveis!
static void Strings(){
String meuChar = "Aqui estamos!";
//método chatAt(int indice), retorna a letra na posição informada
System.out.println(meuChar.charAt(0)); // imprime A
try{
System.out.println(meuChar.charAt(65)); // RuntimeException!
}
catch(StringIndexOutOfBoundsException x){
System.out.println("O índice 65[64] não existe!");
}
//método concat(String x), retorna a string antiga + o que for passado adicionado.
//imprime: Aqui estamos! Fazendo um Teste
System.out.println(meuChar.concat(" Fazendo um Teste"));
//metodo equalsIgnoreCase(String valor), compara duas strings ignorando o case,
//desde que o tamanho seja igual.
//imprime: true false
System.out.print(meuChar.equalsIgnoreCase("AQUI estaMOS!") + " ");
System.out.print(meuChar.equalsIgnoreCase("AQUI estaMOS! ") + "\n");
//metodo length(), retorna o tamanho da string.
//retorna: Tamanho = 13 e Tamanho = 13
System.out.println("Tamanho= " + meuChar.length());
System.out.println("Tamanho= " + meuChar.concat(" > Agora fica legal!").length());
//metodo replace(String sai, String entra), retorna a string reformulada,
//substituindo os caracteres informados
//imprime: Aqui estamos! e Aqui estAmos!
System.out.println("String: " + meuChar + "\n" + "Nova : " + meuChar.replace("a","A"));
//metodo substring(int inicio, int fim), retorna a string reformulada,
//nos limites informados. 'inicio' começa em 0 e 'fim' começa em 1.
//imprime: 'Aqui estamos!' e 'Aqui e'
System.out.println("String: " + meuChar + "\n" + "Nova : " + meuChar.substring(0,6));
//metodo toLowerCase(), retorna a String em Caixa baixa
System.out.println("CaIxaBAixA".toLowerCase());
//metodo toUpperCase(), retorna a String em Caixa alta
System.out.println("caixaalta".toUpperCase());
//método toString(), retorna o valor String do Objeto
//só pode ser usado com objetos, primitivos nao sao objetos!
//Ao chamarmos a partir de uma instancia desta classe, obteremos uma saida
//estranha, <classe>@<valores>, se quisermos podemos sobrescrever
//ou sobrecarregar o método na nossa classe.
//imprime: 'StringsStringBuilderStringBuffer@10b62c9' e 'Este é um objeto!'
StringsStringBuilderStringBuffer x2 = new StringsStringBuilderStringBuffer();
System.out.println(x2 + "\n" + x2.toString(""));
//metodo trim(), retorna a string sem espaços no começo e no fim.
//não tira espaços entre a string.
//imprime: <Sem espaços>
System.out.println("<" + " Sem espaços ".trim() + ">");
//Podemos usar métodos encadeados, a leitura é da esquerda pra direita.
//desde que o método antecessor retorne um tipo que o próximo aceite!
//imprime: AQUIxyXxyX
System.out.println(meuChar.concat(" y ").substring(0,4).concat("xyxxyx").toUpperCase().replace("XY","xy"));
//Strings são imutáveis, não são alteradas!
//Para provar, depois de usarmos todos métodos acima
//a string original nao mudou
//imprime: Aqui estamos!
System.out.println("String: " + meuChar);
//Se apontarmos a referencia para a nova string, mesmo assim esta nao mudara.
//continuara na memória, o que acontece é que será formada uma nova.
//e a referencia será para esta. a antiga se perde.
//imprime: 'aqui estamos! =+='
meuChar = meuChar.toLowerCase() + " =+=";
System.out.println(meuChar);
}
//sobrecarregando o método toString()
//detalhe importante: As classes String, StringBuilder e StringBuffer
//sobrescreveram o método toString(), ou seja, pode ser chamado
//em System.out.println() que retornará o valor que lhe foi dado.
//Quando criamos uma classe, e instanciamos um objeto, se não
//tivermos sobrescrevido o método toString() a saída vai ser estranha.
public String toString(String x){
return "Este é um objeto!";
}
//esse método cobre tudo sobre StringBuilder/StringBuffer
//Existem duas diferenças entre StringBuffer e StringBuilder:
// StringBuilder >
// - Métodos não sao sincronizados (Não é seguro para threads)
// - São mais rápidos
static void StringBuffers(){
//Os objetos stringbuffer e stringbuilder são mutáveis,
//ou seja, ao chamarmos um método ele automaticamente muda na referencia
//e atualiza com o seu resultado.
StringBuffer myChar1 = new StringBuffer("Meu StringBuffer");
//metodo insert(), começando em 0, passamos o índice como parametro
//a partir daquele índice será acrescentado o que for passado
//Obs: O que ficar depois do índice não será perdido, só será "jogado" pra frente.
//Saida: Meu Stri -+- ngBuffer
System.out.println(myChar1.insert(8," -+- "));
//metodo append(), adiciona no final da string.
//Saida: Meu Stri -+- ngBuffer xxxx
System.out.println(myChar1.append(" xxxx"));
//metodo delete(), apaga caractere(s) da string, fornecça os índices.
//obs: o primeiro começa em 0 e o segundo em 1
//neste caso apagou <Meu>, M=0 e u=3
//saida: < Stri -+- ngBuffer xxxx>
System.out.println("<" + myChar1.delete(0,3) + ">");
//metodo reverse(), inverte os caracteres de inicio para fim
//anterior: < Stri -+- ngBuffer xxxx>
//após reverse() - <xxxx reffuBgn -+- irtS >
System.out.println("<" + myChar1.reverse() + ">");
//não conte '<' e '>' como integrantes da string, só usei para
//mostrar espaços em branco.
}
}