Por que os métodos estáticos podem usar somente dados estáticos?

37

Não entendo por que um método estático não pode usar dados não estáticos. Alguém pode explicar quais são os problemas e por que não podemos fazer isso?

    
por JAVA 11.09.2013 / 15:43
fonte

8 respostas

71

Na maioria das linguagens OO, quando você define um método dentro de uma classe, ele se torna um Método de Instância . Quando você cria uma nova instância dessa classe, por meio da palavra-chave new , inicializa um novo conjunto de dados exclusivo para essa instância. Os métodos pertencentes a essa instância podem trabalhar com os dados que você definiu.

Métodos estáticos , em contraste, ignoram instâncias de classes individuais. O método estático é semelhante a uma função livre em C ou C ++. Não está vinculado a uma instanciação específica da classe. É por isso que eles não podem acessar valores de instância. Não há nenhum exemplo para tirar um valor!

Dados estáticos é semelhante a um método estático. Um valor declarado static não tem instância associada. Ele existe para todas as instâncias e só é declarado em um único lugar na memória. Se algum dia for alterado, ele será alterado para cada instância dessa classe.

Um Método estático pode acessar Dados estáticos porque ambos existem independentemente de instâncias específicas de uma classe.

Pode ser útil ver como você chama um método estático, comparado a um método de instância. Digamos que tenhamos a seguinte classe (usando o pseudocódigo do tipo Java):

class Foo {
    // This static value belongs to the class Foo
    public static final string name = "Foo";

    // This non-static value will be unique for every instance
    private int value;

    public Foo(int value) {
         this.value = value;
    }

    public void sayValue() {
        println("Instance Value: " + value);
    }

    public static void sayName() {
        println("Static Value: " + name);
    }
}

Foo foo1 = new Foo(10);
Foo foo2 = new Foo(20);

foo1.sayValue(); // Prints "Instance Value: 10" - called on foo1
foo2.sayValue(); // Prints "Instance Value: 20" - called on foo2

Foo.sayName(); // Prints "Static Value: Foo" - called on Foo (not foo1 or foo2)

Atualizar

Como o COME FROM aponta nos comentários, um método estático é capaz de trabalhar com dados não estáticos, mas deve ser passado explicitamente. Vamos supor que a classe Foo tenha outro método:

public static Foo Add(Foo foo1, Foo foo2) {
    return new Foo(foo1.value + foo2.value);
}

Add ainda é estático e não tem value instâncias próprias, mas como membro da classe Foo, ele pode acessar os campos value privados de foo1 e foo2 transmitidos instâncias. Nesse caso, estamos usando para retornar um novo Foo com os valores adicionados de ambos os valores passados.

Foo foo3 = Foo.Add(foo1, foo2); // creates a new Foo with a value of 30
    
por 11.09.2013 / 16:04
fonte
22

Vamos explicar isso com uma amostra hipotética.

Imagine uma aula simples:

class User
{
User(string n) { name = n; };
string name;
}

Agora criamos duas instâncias dessa classe:

User Bones = new User("Bones");
User Jim = new User("Jim");

agora, pense - e se adicionarmos um novo método estático ao usuário, por exemplo:

static string GetName();

e você chama:

string x = User::GetName()

o que x conteria? "Jim", "Bones", ou algo mais?

O problema é que um método estático é um método único, definido na classe, não nos objetos. Como resultado, você não sabe qual objeto pode ser aplicado. É por isso que é uma coisa especial. É melhor pensar em métodos estáticos como coisas individuais, como funções em C, por exemplo. Que linguagens como Java as contêm dentro de classes é principalmente um problema com Java não permitindo que nada exista fora de uma classe, então funções como essa precisam ser forçadas dentro de uma classe de alguma maneira (um pouco como main () é forçado a ser dentro de uma classe também, quando todo sentido diz que deve ser uma função singular e independente).

    
por 11.09.2013 / 16:08
fonte
2

Dados não estáticos estão associados a uma instância da classe. Métodos estáticos (e dados) não estão associados a uma instância específica da classe. Não precisa haver uma instância de uma classe para usar métodos estáticos nela. Mesmo se houvesse instância (s), não haveria como o Java garantir que você está operando na instância que está esperando quando chama um método estático. Portanto, os métodos estáticos não podem ter acesso a dados não estáticos.

    
por 11.09.2013 / 15:57
fonte
2

Pode usar dados de campo; considere o seguinte código java:

class MyBean {
    private String myString;

    static void myStaticMethod() {
        myString = "tada";/*not allowed; if this was possible how would 
                           be different from a field without static?*/

        MyBean myBean = new MyBean();//allowed if associated with an instance
        myBean.myString = "tada";
    }
}
    
por 11.09.2013 / 16:03
fonte
2

Acho que a questão aqui é de compreensão.

Do ponto de vista técnico, um método estático chamado de dentro de um objeto seria bastante capaz de ver os campos da instância. Eu suspeito strongmente que foi isso que causou a pergunta em primeiro lugar.

A questão é que os métodos podem ser chamados de fora do objeto. Nesse ponto, não há dados de instância para fornecê-los - e, portanto, não há como o compilador resolver o código. Como permitir que dados de instância causem uma contradição, não devemos permitir dados de instância.

    
por 02.05.2014 / 23:00
fonte
1

Pense nisso como métodos estáticos vivendo em uma dimensão não orientada a objetos.

Na "dimensão orientada a objetos", uma classe pode gerar múltiplos egos (instâncias), cada ego tem consciência de si mesmo através de seu estado.

Na dimensão plana, não OO, uma classe ignora seus egos vivendo na dimensão OO. O mundo deles é plano e processual, quase como se a OOP ainda não tivesse sido inventada e como se a classe fosse um pequeno programa processual, e os dados estáticos fossem apenas variáveis globais.

    
por 11.09.2013 / 17:01
fonte
1

Acho que a maneira mais fácil de explicar isso é examinar um código e, em seguida, considerar quais resultados esperaríamos que o código produzisse.

// Create three new cars.  Cars have a name attribute.  
Car car1 = new Car("Mazda3");
Car car2 = new Car("FordFocus");
Car car3 = new Car("HondaFit");

// Now we would like to print the names of some cars: 
// First off why don't we try this: 

Car.printCarName();

// Expected behaviour: 
// If we think about what we are trying to do here it doesn't
// really make sense.  What instance of car name should this 
// print?  Should it print Mazda3?  FordFoucs?
// What is the expected behaviour?  If we are going to have a
// static call on car call printCarName it should probably do
// something like print all car names or a random car name or
// throw an error.  


//Now lets try this instead: 

Car.printCarName(car1);

// Expected Behaviour: 
// Luckily the expected behaviour is very clear here.  This
// should print Mazda3.  This works as expected.  


// Finally lets try this: 

car1.printMyName();

// Expected Behaviour:
// Same as previous example, however this is the *right* way
// to do it.  

Para completar, aqui está a classe do carro:

public class Car{

    public String name;

    public Car(String name){
        this.name = name;
    }

    public static printCarName(){
        print "Not sure what to do here...  Don't know which car you are talking about.";
    }

    public static printCarName(Car c){
        print c.name;
    }

    public /*NOT static*/ printMyName(){
        print this.name;
    }

}
    
por 12.09.2013 / 00:30
fonte
1

As outras respostas praticamente dizem tudo, no entanto, há alguns "detalhes" que gostaria de adicionar.

Métodos estáticos (digamos, aqueles em Java) simplesmente não possuem um objeto implícito associado a eles (acessível através de this ) cujos membros você pode acessar geralmente diretamente pelo nome.

Isso não significa que eles não possam acessar dados não estáticos. %pr_e%

Eu sei que isso é apenas um detalhe, mas eu achei sua pergunta estranha quando a li. "Pode usar apenas dados estáticos" é muito restritivo.

A propósito, eu não testei o código, eu apenas o escrevi aqui para exemplificar o que eu estava dizendo.

    
por 12.09.2013 / 22:27
fonte

Tags