Enviar um café pro programador

Pode me ajudar a transformar cafeína em código?

private, public e protected: Protegendo suas informações em Java

Já vimos a relação de membros e métodos definidos como public e private, bem como a relação deles com o restante da aplicação.

Sabemos que membros private não podem ser acessados fora da classe em que foram declarados.
Mas em relação as suas subclasses?
E se eu quiser esconder algum dado das subclasses?

Veremos nesse artigo, de nosso curso online de Java, como proteger membros de uma classe, limitar e controlar o acesso aos dados importantes.

Herança de atributos public

Atributos public não tem segredo. Podem ser 'vistos' e acessados de qualquer parte de uma aplicação Java.

Na prática, elementos public são utilizados em variáveis e métodos universais, onde não há problema nem necessidade de segurança daquele dado. Exemplo: horas, constantes, variáveis globais, nome do programa ou da empresa etc.

O nome já fala tudo por si só, é público.


Herança de atributos private

Diferente dos elementos public, os private são informações 'escondidas', ou no mínimo controladas.

Por exemplo, é bem comum ver todas as variáveis de uma classe definidas como priva, e usar métodos public do tipo set, para dar um valor a esta variável.
Ora, se o set() for só para definir o valor da variável, essa atitude é totalmente inútil.
Só devemos usar o set() para manipular variáveis private quando fizemos algo a mais, como checar se o valor recebido é positivo, se está dentro do intervalo que esperamos ou mesmo para contar quantas vezes aquela variável foi acessada.

Isso tudo tem um motivo: variáveis private não podem ser acessadas nem por suas subclasses.
Tenha isso em mente: priva é sinônimo de segurança.

O seguinte exemplo, dando continuidade aos exemplos de Herança de nossa tutorial de Java passado, vamos mostrar que é impossível acessar diretamente a variável 'senhaPai' a partir da subclasse "Filha":

-->Heranca.java
public class Heranca {

    public static void main(String[] args) {
        Filha filha = new Filha();
    }

}


-->Pai.java
public class Pai {

    private String senhaPai;
    
    public Pai(){
        this.senhaPai = "papaidanadao";
    }
    
}


-->Filha.java
public class Filha extends Pai {
    
    public Filha(){
        
        System.out.println(senhaPai);
    }
    
}


Obteremos o seguinte erro:
"The field Pai.senhaPai is not visible"

Literalmente: o campo Pai.senhaPai não é visível. Nem pra classe filha a senha da classe pai é vista.
Isso que é segurança, hein?
Pense bem se seus atributos devem ser private ou não. Lembre-se que se não forem, outras pessoas - hackers - podem usar isso para obter informações de sua aplicação.





Herança de atributos protected

Vamos agora introduzir outro modo de declarar seus atributos, o modificador de acesso protected.

O protected é pra quando você não quer deixar um atributo public, livre para todos.
Porém, você quer compartilhar ele com as subclasses. O protected é um intermediário entre public e private.
É um segredo de família.

Por família entende: a superclasse, as subclasses e classes do mesmo package.
Para todos as outras classes, atributos protected são invisíveis. Ou seja, estamos protegendo do acesso externo.

Outro detalhe importante: quando atributos são declarados como public ou protected, eles continuarão como public ou protected.
Lembra que dissemos que subclasses podem ser superclasse também? Ora, basta declarar outra classe que extends a classe Filha, e teremos uma subclasse da subclasse Filha.

Então, vamos chamar essa classe de Neta.
Se declararmos uma variável como protected na classe Pai, ela será protected na classe Filha, e será vista como protected na classe Neta. O mesmo para public.

Vamos criar dois pacotes: o package "Familia", que irá conter as classes "Heranca", "Pai", "Filha" e "Neta ; e o pacote "Vizinho", que contém a classe "Vizinho".

Para fazer isso basta escrever no início: package Familia ou package Vizinho
A senha do pai poderá ser vista por qualquer um do pacote "Familia", mas obteremos um erro quando tentarmos ver essa senha através da classe "Vizinho", pois o vizinho não faz parte do pacote "Familia".

Nosso exemplo ficará assim:

-->Heranca.java
package familia;
import Vizinho.Vizinho;

public class Heranca {

    public static void main(String[] args) {
        Neta neta = new Neta();
        
        System.out.println("Senha vista da classe Herança: "+neta.senhaPai);
        
        Vizinho vizinho = new Vizinho(neta);
        
        
    }
}




-->Pai.java
package familia;

public class Pai {

    protected String senhaPai;
    
    public Pai(){
        this.senhaPai = "papaidanadao";
    }
    
}



-->Filha.java
package familia;

public class Filha extends Pai {
    
    public Filha(){
        System.out.println("Senha vista pela filha: "+senhaPai);
    }
    

}



-->Neta.java
package familia;

public class Neta extends Filha{
    
    public Neta(){
        System.out.println("Senha vista pela Neta: " + senhaPai);
    }
}



-->Vizinho.java
package Vizinho;
import familia.Neta;

public class Vizinho {
    public Vizinho(Neta neta){
        System.out.println("Senha vista pelo vizinho: "+neta.senhaPai);        
    }
}



Obtemos o resultado:
Senha vista pela filha: papaidanadao
Senha vista pela Neta: papaidanadao
Senha vista da classe Herança: papaidanadao
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The field Pai.senhaPai is not visible

Ou seja, podemos ver a senha do Pai por qualquer uma das subclasses e classes do pacote "Familia".
Porém, ao tentarmos ver por uma classe que não faz parte nem do pacote "familia" nem é subclasse de "Pai", "Filha" ou "Neta" obtemos um erro, pois a senha do pai não será visível para o vizinho.

Seguro esse Java, não?
Não é à toa que ele é bastante usado por empresas, como seu bank online. Pode confiar no Java!

9 comentários:

Anônimo disse...

Copiei os códigos acima e tentei executalos, da erro de compilacao 5 erros, poderiam me ajudar com isto!?

Java Progressivo disse...

Claro, copie e cole os erros que apareceram.

Unknown disse...

Primeiramente queria dizer que na minha opinião este é um dos melhores sites de aprendizagem, gosto bastante de sua metodologia e dicas. Parabéns!

Gostaria de saber o seguinte, se uma variável de instância do tipo private 'melhora' na questão da segurança, uma invasão de um hackers por exemplo, como estes não conseguem visualizar a informação da variável se ele pode utilizar os métodos setts e getts para atribuir e retornar o valor dela?

anotador disse...

Já tinha bastante experiência de programação em outras linguagens mas torcia o nariz para Java diante do que já havia visto.
O seu curso, muito bem estruturado, acabou com todos os meus preconceitos. :)
Parabéns!

Anônimo disse...

Kleber JS,
Os métodos Getters e Setters, de fato, permitiriam acesso não autorizado se forem utilizados sem prescrição alguma. Isso depende do programador, e como uma boa prática de programação você deve utilizar tais métodos se forem realmente necessários, ou seja, quando você realmente querer que uma outra classe veja e/ou altera os dados em uma variável. O que quero dizer é que você deve ter em mente o acesso que você quer permitir a outras classes, pois, talvez, algo pode não sair bem como pensou.

Unknown disse...

Muito bom! Fantásticas suas explicações neste site! É minha referência agora!!!

abraços!!!

Unknown disse...

Ótimo exemplo. Mas o que acha de colocar uma outra situação na qual o vizinho herda de Neta (um familiar que é vizinho). Neste caso, ficaria mais fácil de diferenciar da visibilidade default.

MODIDIFICADOR | Clase | Mesmo pacote | Pacote diferente (subclasse) | Pacote diferente (global)
public x x x x
protected x x x
default x x
private x

package vizinho;
import familia.Neta;

public class Vizinho extends Neta{
public Vizinho(){
System.out.println("Senha vista pelo vizinho: "+senhaPai);
}
}

Anônimo disse...

Para funcionar tive que mudar no inicio a opção Criar Classe Principal de
heranca.Heranca para familia.Familia, de modo que criou Familia.Java e não Heranca.Java.

Também tive que mudar no programa principal, onde tem o main...
de public class Heranca {
para public class Familia {

Anônimo disse...

Muito bem explicado, parabéns !!

Contribuir com o Java Progressivo

Que tal apoiar e fazer crescer o ensino da programação no Brasil ?

Ajudar nosso país a crescer e se desenvolver cada vez mais, tecnologicamente?

Clica abaixo pra saber mais!

Apoiar o Projeto Progressivo


Tutoriais de Java