Com o operador instanceof é possível saber se o Objeto em uma variável é de determinada classe, mas, existiria algum jeito em Java de se saber se um Objeto em uma variável é Mutável ou Imutável? Ou eu vou ter que criar Ifs com vários instanceof verificando se o Objeto pertence a uma Classe que eu já sei que é imutável (como String, Integer, Double, etc…)?
Exemplo:
`public boolean isImutavel(Object o)` {
if (o instanceof String) return true;
if (o instanceof Integer) return true;
if (o instanceof Double) return true;
...
return false; /*Retorna false se o Tipo do Objeto é desconhecido ou ele não é Imutável*/
}
Ainda não. Infelizmente, Java não tem nenhum recurso de imutabilidade explícito para uma classe, mas só para atributos de uma classe ou variáveis, o final.
Eu acredito que, por causa do trending a respeito de imutabilidade dos últimos anos, que tem se propagado ainda mais por causa do paradigma funcional (além dos benefícios quando estamos utilizando concorrência), uma versão futura do Java vai trazer isso.
[Gambiarra Alert] O que você pode fazer é criar uma anotação, pode chamar de @Immutable, ou @Imutavel, e verificar se a classe daquele objeto possui essa anotação (através de Reflection), e anotar as classes que você constrói, e que são realmente imutáveis. É um workaround que funciona, mas o compilador não vai te ajudar nessa.
Eu acho que seria um pouco mais fácil, já que o uso de reflection não seria necessário, mas sim o operador instanceof mesmo, como você fez no teu exemplo. Porém, como na sugestão que eu te falei, não tem como aplicar aos tipos da linguagem (como String, por exemplo).
O que é impossível de se fazer é verificar programaticamente se um objeto é, por definição, imutável. Isso não impede, de forma alguma, que objetos efetivamente imutáveis sejam criados, através de encapsulamento e da não publicação (ou escape) de referências internas, seja através de getters, ou de qualquer outro método.
Exemplo de mutabilidade com clara de imutabilidade:
final class MutavelComCaraDeImutavel {
private final ArrayList<Integer> numeros = new ArrayList<>();
final public List<Integer> getNumeros() {
return numeros; // escape de referência interna. A partir daqui, não se sabe mais o que vai acontecer com o conteúdo dessa lista.
}
}