CodeGym/Blogue Java/Random-PT/Valores fixos em Java: final, constantes e imutáveis
John Squirrels
Nível 41
San Francisco

Valores fixos em Java: final, constantes e imutáveis

Publicado no grupo Random-PT
Oi! Você já está familiarizado com a palavra "modificador". No mínimo, você encontrou modificadores de acesso (público, privado) e o modificador estático. Hoje discutiremos um modificador especial chamado final . Você poderia dizer que o modificador final "cimenta" partes do nosso programa onde comportamentos constantes, inequívocos e imutáveis ​​são necessários. Existem três locais em seus programas onde você pode usá-lo: classes, métodos e variáveis. Valores fixos em Java: final, constantes e imutáveis ​​- 2 Vamos percorrê-los em ordem. Se o modificador final for usado em uma declaração de classe, isso significa que a classe não pode ser herdada. Nas lições anteriores, usamos um exemplo simples de herança: tínhamos uma Animalclasse pai e duas classes filhas: CateDog
public class Animal {
}



public class Cat extends Animal {
   // Fields and methods of the Cat class
}


public class Dog extends Animal {

   // Fields and methods of the Dog class
}
No entanto, se usarmos o modificador final na Animalclasse, as classes Cate Dognão poderão herdá-lo.
public final class Animal {

}

public class Cat extends Animal {

   // Error! Cannot inherit from final Animal
}
O compilador gera imediatamente um erro. Em Java, muitas classes finais já estão implementadas. Entre aqueles que você usa com frequência, Stringé o mais conhecido. Além disso, se uma classe for declarada como final , todos os métodos da classe também se tornarão finais . O que isso significa? Se um método for declarado usando o modificador final , você não poderá substituir esse método. Por exemplo, aqui temos uma Animalclasse que declara um speak()método. Mas cães e gatos definitivamente "falam" de maneiras diferentes. Portanto, declararemos métodos speak() nas classes Cate Dog, mas os implementaremos de maneira diferente.
public class Animal {

   public void speak() {
       System.out.println("Hello!");
   }
}

public class Cat extends Animal {

   @Override
   public void speak() {
       System.out.println("Meow!");
   }
}

public class Dog extends Animal {

   @Override
   public void speak() {
       System.out.println("Woof!");
   }
}
Fizemos as Catclasses e Dogsubstituir o método declarado na classe pai. Agora, um animal vai falar diferente, dependendo do tipo de objeto que é:
public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       Dog dog = new Dog();

       cat.speak();
       dog.speak();
   }
}
Saída: Miau! Uau! No entanto, se declararmos o método Animalda classe speak()como final, não poderemos substituí-lo em outras classes:
public class Animal {

   public final void speak() {
       System.out.println("Hello!");
   }
}


public class Cat extends Animal {

   @Override
   public void speak() {// Error! A final method can't be overridden!
       System.out.println("Meow!");
   }
}
E nossos objetos serão forçados a usar o speak()método definido na classe pai:
public static void main(String[] args) {

   Cat cat = new Cat();
   Dog dog = new Dog();

   cat.speak();
   dog.speak();
}
Saída: Olá! Olá! Agora, em relação às variáveis ​​finais . Eles também são conhecidos como constantes . Primeiro (e mais importante), o valor inicial atribuído a um valor constante não pode ser alterado. É atribuído de uma vez por todas.
public class Main {

   private static final int CONSTANT_EXAMPLE = 333;

   public static void main(String[] args) {

       CONSTANT_EXAMPLE = 999;// Error! You can't assign a new value to a final variable!
   }
}
Uma constante não precisa ser inicializada imediatamente. Isso pode ser feito mais tarde. Mas, o valor inicialmente atribuído a ela permanecerá o mesmo para sempre.
public static void main(String[] args) {

   final int CONSTANT_EXAMPLE;

   CONSTANT_EXAMPLE = 999;// This is allowed
}
Em segundo lugar, observe o nome da nossa variável. Java tem uma convenção de nomenclatura diferente para constantes. Não é a notação camelCase usual . Se fosse uma variável comum, teríamos chamado de constanteExample. Porém, os nomes das constantes são escritos em letras maiúsculas, com sublinhados entre as palavras (se houver mais de uma palavra), por exemplo, "CONSTANT_EXAMPLE". Por que precisamos de constantes? Eles são muito úteis se, por exemplo, houver um valor fixo que você usa regularmente em um programa. Por exemplo, você decidiu fazer história e escrever o jogo "The Witcher 4" sozinho. Obviamente, o jogo usará regularmente o nome do protagonista: "Geralt of Rivia". Essa string (e os nomes de outros heróis) é melhor declarada como uma constante: seu valor será armazenado em um lugar e você definitivamente não cometerá um erro de digitação ao digitá-lo um milhão de vezes.
public class TheWitcher4 {

   private static final String GERALT_NAME = "Geralt of Rivia";
   private static final String YENNEFER_NAME = "Yennefer of Wengerberg";
   private static final String TRISS_NAME = "Triss Merigold";

   public static void main(String[] args) {

       System.out.println("The Witcher 4");
       System.out.println("It's already the fourth Witcher game, but " + GERALT_NAME + " still can't decide who" +
               " he likes more: " + YENNEFER_NAME + " or " + TRISS_NAME);

       System.out.println("But, if you've never played The Witcher before, we'll start from the beginning.");
       System.out.println("The protagonist's name is " + GERALT_NAME);
       System.out.println(GERALT_NAME + " is a witcher, a monster hunter");
   }
}
Resultado: The Witcher 4 Já é o quarto jogo de Witcher, mas Geralt de Rivia ainda não consegue decidir de quem gosta mais: Yennefer de Wengerberg ou Triss Merigold Mas, se você nunca jogou The Witcher antes, vamos começar do começo. O nome do protagonista é Geralt de Rivia Geralt de Rivia é um bruxo, um caçador de monstros Declaramos os nomes dos heróis como constantes. Agora definitivamente não cometeremos erros de digitação e não há necessidade de escrevê-los à mão todas as vezes. Outra vantagem: se precisarmos alterar o valor da variável em todo o programa, você pode fazer isso em um só lugar, em vez de modificá-lo manualmente em toda a base de código. :)

Tipos imutáveis

Como você trabalhou com Java, provavelmente já se acostumou com a ideia de que os programadores têm controle quase total sobre o estado de todos os objetos. Se você quiser criar um Catobjeto, você pode. Se você quiser renomeá-lo, você pode. Se você quiser mudar sua idade ou outra coisa, você pode. Mas Java tem vários tipos de dados que possuem uma propriedade especial. Eles são imutáveis . Se uma classe é imutável, o estado de seus objetos não pode ser alterado. Quer alguns exemplos? Você pode se surpreender, mas a classe imutável mais conhecida é a String! Então, realmente não podemos alterar o valor de uma String? Bem, vamos tentar:
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;// Both reference variables point to the same string.
   System.out.println(str2);

   str1 = "I love Python";// but changing str1 has no impact on str2
   System.out.println(str2);// str2 continues to point to the "I love Java" string, but str1 now points to a different object
}
Saída: Eu amo Java Eu amo Java Depois que escrevemos
str1 = "I love Python";
o "I love Java"objeto string não mudou ou foi a lugar nenhum. Ele ainda existe felizmente e tem exatamente o mesmo texto de antes. O código
str1 = "I love Python";
simplesmente criou outro objeto, para o qual str1 agora aponta. Mas parece que não conseguimos ter nenhum efeito no objeto string "I love Java". Ok, vamos tentar outra coisa! A Stringclasse está cheia de métodos, e alguns deles parecem mudar o estado do objeto! Por exemplo, há um replace()método. Vamos mudar a palavra "Java" para "Python" em nossa string!
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;// Both reference variables point to the same string.
   System.out.println(str2);

   str1.replace("Java", "Python");// We try to change the state of str1 by swapping the word "Java" with "Python"
   System.out.println(str2);
}
Saída: Eu amo Java Eu amo Java Não funcionou de novo! Talvez o método replace não funcione? Vamos tentar outra coisa. Por exemplo, substring(). Ele retorna uma substring baseada em índices de caracteres passados ​​como argumentos. Vamos cortar os primeiros 10 caracteres da nossa string:
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;// Both reference variables point to the same string.
   System.out.println(str2);

   str1.substring(10);// Truncate the original String
   System.out.println(str2);
}
Saída: Eu amo Java Eu amo Java Valores fixos em Java: final, constantes e imutáveis ​​- 3 Nada mudou. E não deveria. Como dissemos anteriormente, Strings são imutáveis. Então, o que há com todos os métodos da Stringclasse? Afinal, eles podem truncar strings, alterar caracteres e muito mais. Qual é o ponto se nada acontecer? Eles realmente podem fazer essas coisas! Mas, eles retornam uma nova String toda vez. É inútil escrever
str1.replace("Java", "Python");
porque você não pode alterar o objeto original. Mas, se você escrever o resultado do método em uma nova variável de referência, verá a diferença imediatamente!
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;// Both reference variables point to the same string.
   System.out.println(str2);

   String str1AfterReplacement =  str1.replace("Java", "Python");
   System.out.println(str2);

   System.out.println(str1AfterReplacement);
}
Todos Stringos métodos funcionam dessa maneira. Nada pode ser feito ao "I love Java"objeto. Você pode simplesmente criar um novo objeto e escrever: "<novo objeto> = o resultado da manipulação do "I love Java" object ". Quais outros tipos são imutáveis? Alguns que você definitivamente precisa lembrar imediatamente são todas as classes wrapper para os tipos primitivos. Integer, Byte, Character, Short, Boolean, Long, Double, Float: todas essas classes criam immutableobjetos (falaremos sobre elas nas próximas lições). Isso inclui classes usadas para criar números grandes, como BigIntegere BigDecimal. Recentemente, cobrimos exceções e abordamos o rastreamento de pilha . Bem , adivinhe, java.lang.StackTraceElementobjetos também são imutáveis. Isso faz sentido: se alguém pudesse alterar os dados de nossa pilha, isso tornaria tudo inútil. Imagine alguém passando pelo rastreamento de pilha e alterando um OutOfMemoryError para um FileNotFoundException . E então você usa essa pilha para encontrar a causa do erro. Mas o programa nem usa arquivos. :) Então, eles tornaram esses objetos imutáveis, só para garantir. Ok, então faz mais ou menos sentido para StackTraceElement . Mas, por que alguém precisaria tornar Strings imutáveis? Por que mudar seus valores seria um problema? Provavelmente seria ainda mais conveniente. :/ Há várias razões para isso. Primeiro, ele economiza memória. Strings imutáveis ​​podem ser colocadas no pool de strings, permitindo que strings sejam reutilizadas em vez de criar novas. Segundo, por segurança. Por exemplo, nomes de usuários e senhas são Strings em quase todos os programas. Tornar possível alterá-los pode resultar em problemas de autorização. Há outras razões, mas nosso estudo de Java ainda não as cobriu, então voltaremos a elas mais tarde.
Comentários
  • Populares
  • Novas
  • Antigas
Você precisa acessar para deixar um comentário
Esta página ainda não tem nenhum comentário