Por que o Java nos permite compilar uma classe com um nome diferente do nome do arquivo?

170

Eu tenho um arquivo Test.javae o seguinte código dentro dele.

public class Abcd
{
        //some code here

}

Agora a classe não compila, mas quando eu removo o publicmodificador, ela compila bem.

Qual é o raciocínio por trás do Java que nos permite compilar um nome de classe que é diferente do nome do arquivo quando não é público.

Eu sei que é uma pergunta para iniciantes, mas não consigo encontrar uma boa explicação.

user2434
fonte
28
Porque Java. (Porque não é público, e não tem que seguir a mesma convenção de nomenclatura Além disso, você precisa perguntar as pessoas que a inventaram..)
Dave Newton
2
Duvido que exista uma "boa explicação". Era um requisito para classes públicas, mas era considerado desnecessário para classes não públicas.
Kayaman
2
Parece uma pergunta semelhante: stackoverflow.com/questions/7633631/...
Sanket
4
Por que tantas upvotes para esta questão, antes de tudo sua questão duplicado: stackoverflow.com/questions/7633631/...
GM Ramesh
2
@ Ramesh: título e conteúdo desta questão é melhor .. (do que os outros semelhantes)
Jayan

Respostas:

325

A lógica é permitir mais de uma classe de nível superior por .javaarquivo.

Muitas classes, como ouvintes de eventos, são apenas de uso local e as versões mais antigas do Java não suportam classes aninhadas. Sem esse relaxamento da regra "nome do arquivo = nome da classe", cada uma dessas classes exigiria seu próprio arquivo, com o resultado inevitável da proliferação infinita de .javaarquivos pequenos e da dispersão de códigos fortemente acoplados.

Assim que o Java introduziu classes aninhadas, a importância dessa regra diminuiu significativamente. Hoje você pode passar por centenas de arquivos Java, nunca se deparando com um que tire proveito dele.

Marko Topolnik
fonte
60
+1, isso realmente fornece um motivo , que é a questão.
Dave Newton
4
+1 para informações históricas, especialmente - suspeito que, com o advento das classes aninhadas / anônimas, se a mesma decisão fosse tomada agora (sem se importar com a compatibilidade com versões anteriores), faria muito mais sentido permitir apenas uma classe de nível superior por Arquivo.
Michael Berry
1
@ berry120 Muito provavelmente, porque este subsídio complica a pesquisa de arquivos durante a compilação.
Marko Topolnik
3
@Val Negar que outras pessoas prefiram usar um editor de texto e ferramentas de CLI para desenvolver porque você o IDE que você prefere é tão bobo quanto dizer que não há sentido em criar IDEs porque você pode fazer o desenvolvimento sem eles. Ambas as abordagens são usadas por bons desenvolvedores para criar código de qualidade; e a única coisa menor que as chances de todos os desenvolvedores escolherem um deles e cantarem kumbaya são as chances de que todos concordemos sobre qual é a melhor linguagem de programação.
Dan Is Fiddling Por Firelight
5
A combinação do Emacs (ou Vim, escolha seu veneno) e os utilitários shell do Unix talvez não sejam tudo ao seu alcance como um IDE moderno, e certamente são mais difíceis de aprender, mas têm duas vantagens impressionantes em comparação com todo IDE que eu já tentei: eles nunca travam, por maior que seja a base de código, e podem acompanhar minha digitação.
Zwol
80

O motivo é o mesmo para as placas da porta. Se uma pessoa reside oficialmente no escritório (público declarado), seu nome deve estar na etiqueta da porta. Como "Alex Jones" ou "Detetive Colombo". Se alguém apenas visita a sala, conversa com um funcionário ou limpa o chão, seu nome não precisa ser oficialmente colocado na porta. Em vez disso, a porta pode ler "Utilitários" ou "Sala de reunião".

Nome oficial ou MyClass.java Sala de reunião ou Test.java

exebook
fonte
4
Definitivamente uma analogia interessante; pode ser ainda melhor com um pouco de explicação de como isso se relaciona diretamente. O OP pode ter alguma dificuldade em fazer a conexão (embora eu entendo perfeitamente)
Andrew Barber
4
@AndrewBarber Eu não acho que a analogia realmente se encaixa, pois não modela a classe pública única, compartilhando o arquivo com várias classes privadas de pacote. É como a placa da porta com a inscrição "Heather Santee, gerente", mas a sala na verdade contém Heather e suas duas secretárias.
Marko Topolnik
@MarkoTopolnik Eu não deveria ter me envolvido nisso; Eu sou classe A horrível em analogias! ;)
Andrew Barber
@AndrewBarber Eu queria escrever de qualquer maneira; você apenas deu um empurrão :) A analogia também falha em expressar a preocupação mais aguda: devido a esse recurso, o compilador deve analisar todos os arquivos para descobrir todas as classes onde, caso contrário, ele poderia apenas ler a lista de diretórios e saber os nomes de todos. classes de nível superior.
Marko Topolnik
@AndrewBarber, a analogia se encaixa perfeitamente na idéia de diretório, no longo corredor você pode encontrar rapidamente uma pessoa apenas olhando as placas da porta, não precisa entrar em cada quarto e perguntar.
exebook
29

A especificação Java afirma que você só pode ter no máximo uma classe pública por arquivo. Nesse caso, o nome da classe deve corresponder ao nome do arquivo. Todas as classes não públicas podem ter qualquer nome, independentemente do nome do arquivo.

Andrei Nicusan
fonte
20
Mas "qual é o raciocínio por trás do Java que nos permite" isso?
Marko Topolnik
@MarkoTopolnik Porque isso não nos impede: D
Maroun
8
@MarounMaroun Mas qual é o raciocínio por trás de não nos impedir?
Marko Topolnik
O @Marko Java permite ter várias classes definidas no mesmo arquivo (desde que apenas uma delas seja pública). Como todas as classes dentro do mesmo pacote devem ter um nome diferente, não há outra opção além de permitir que classes não públicas tenham um nome diferente do nome do arquivo.
Isnot2bad #
2
Meus 2 centavos: talvez tenha sido projetado dessa maneira para uma localização mais rápida das classes dentro do caminho de classe. Com esta convenção, inspecionar os nomes / caminhos dos arquivos é suficiente para a descoberta de classes. Sem esta convenção, o carregador de classe classpath pode precisar abrir e arquivos de análise a fim de encontrar as classes
Andrei Nicusan
13

Eu acho que permiti-los é um pré-requisito para classes aninhadas. Classes anônimas, em particular, reduzem drasticamente o número de arquivos .java necessários. Sem suporte para isso, você precisaria de muitas implementações de interface de método único em seus próprios arquivos separados da classe principal em que são usados. (Estou pensando em ouvintes de ação em particular)

Há uma boa explicação de todas as classes aninhadas no tutorial Java de classes aninhadas no site da Oracle, que possui exemplos de cada uma. Ele também tem um motivo para serem úteis, que cito:

Por que usar classes aninhadas?

Os principais motivos para o uso de classes aninhadas incluem o seguinte:

  • É uma maneira de agrupar logicamente classes que são usadas apenas em um lugar : se uma classe é útil para apenas uma outra classe, é lógico incorporá-la nessa classe e manter as duas juntas. Aninhar essas "classes auxiliares" torna seu pacote mais otimizado.

  • Aumenta o encapsulamento : considere duas classes de nível superior, A e B, em que B precisa acessar membros de A que, de outra forma, seriam declarados privados. Ao ocultar a classe B na classe A, os membros de A podem ser declarados privados e B pode acessá-los. Além disso, o próprio B pode ser oculto do mundo exterior.

  • Isso pode levar a um código mais legível e de manutenção : o aninhamento de pequenas classes nas classes de nível superior coloca o código mais perto de onde ele é usado.

(ênfase minha)

Não estou familiarizado com as especificações Java nos primeiros dias, mas uma pesquisa rápida mostra que classes internas foram adicionadas no Java 1.1.

Joshua McKinnon
fonte
O que se deve fazer nos casos em que um tipo é útil apenas em outro tipo, mas as instâncias do tipo anterior não estão associadas às instâncias do último?
Supercat 26/11
Classes aninhadas são a maneira do Java 1.2 de executar lambdas ou 'Funções de primeira classe quando tudo é um objeto'. Isso está mudando na sintaxe 1.8. Eles também são usados ​​quando queremos modelar tipos de dados algébricos no sistema Type de Java.
hawkeye
12

Eu olho para o contrário. O estado natural das coisas seria o programador escolher o nome da classe e o nome do arquivo independentemente. Provavelmente, para simplificar a localização de classes públicas de fora de um pacote durante a compilação, há uma restrição especial de que uma classe pública esteja em um arquivo com o nome correspondente.

Patricia Shanahan
fonte
4

Observe que Java diferencia maiúsculas de minúsculas, mas o sistema de arquivos não precisa ser. Se o nome base do arquivo for "abcd", mas a classe for "Abcd", isso seria compatível com a regra em um sistema de arquivos que não diferencia maiúsculas de minúsculas? Certamente não quando portado para um que diferencia maiúsculas de minúsculas.

Ou suponha que você tenha uma classe chamada ABCD e uma classe Abcd (não vamos deixar de ser uma má idéia: isso pode acontecer) e o programa é portado para um sistema de arquivos que não diferencia maiúsculas de minúsculas. Agora você não apenas precisa renomear arquivos, mas também classes, oops!

Ou e se não houver arquivo? Suponha que você tenha um compilador Java que possa receber entrada na entrada padrão. Então a classe deve ser nomeada "StandardInput"?

Se você explorar racionalmente as implicações de exigir que os nomes de arquivos sigam os nomes das classes, você descobrirá que é uma má ideia de mais de uma maneira.

Kaz
fonte
Concordo com o que você tem a dizer, mas não sei se isso responde particularmente à pergunta, exceto, talvez, na medida em que alguns dos problemas resultantes da arquitetura de nomenclatura possam ser atenuados, permitindo que nomes de classes não públicos sejam diferentes de nomes de arquivos. BTW, em relação a maiúsculas e minúsculas, se eu estivesse derivando uma língua, em qualquer âmbito foram Foofoi declarado, os identificadores FOO, foo, fOo, etc. seriam todos "indefinido", mesmo que existia dentro escopos externos. Esse design eliminaria o problema de distinção entre maiúsculas e minúsculas nos nomes de arquivos.
Supercat 26/11
3

Outro ponto que muitas respostas não foram apontadas é que, sem a publicdeclaração, a JVM nunca saberia qual método principal de classes precisa ser chamado. Todas as classes declaradas em um arquivo .java podem ter métodos principais, mas o método principal é executado apenas na classe marcada como pública. HTH

happybuddha
fonte
0

Como um arquivo java pode conter mais de uma classe, ele pode ter duas classes em um arquivo java. Mas um arquivo java deve conter uma classe com o mesmo nome que o nome do arquivo, se contiver uma classe pública.

podongfeng
fonte
Não, essa regra é aplicável apenas a classes públicas.
deadboy