AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 77673480
Accepted
user2153235
user2153235
Asked: 2023-12-17 14:19:19 +0800 CST2023-12-17 14:19:19 +0800 CST 2023-12-17 14:19:19 +0800 CST

Por que Java exige "novo" quando se entende que um construtor cria uma nova instância [duplicada]

  • 772
Esta pergunta já tem respostas aqui :
A palavra-chave `new` em java é redundante? (5 respostas)
Por que java tem novidades? [duplicado] (6 respostas)
Fechado há 10 horas .

Naveguei na web em busca do uso de "novo" em Java e é para criar uma nova instância de classe. Por que isso exige indicação explícita por meio da palavra-chave “nova”? Não está entendido que uma invocação de construtor instancia um novo objeto? Sem new, por exemplo, fica claro que MyClass AnInstance = MyClass(AnArgument)cria um novo objeto.

De uma perspectiva prática, meu motivo para perguntar é porque presumo que “novo” foi projetado para proteger contra um perigo e quero estar ciente do perigo.

java
  • 4 4 respostas
  • 133 Views

4 respostas

  • Voted
  1. WestCoastProjects
    2023-12-17T14:39:12+08:002023-12-17T14:39:12+08:00

    Correndo o risco de uma resposta ser considerada "uma opinião", eu jogaria fora o que javaseguiu C e C++ e essencialmente herdei a sintaxe deste último - mesmo que o análogo destroyfosse desnecessário, dado o coletor de lixo.

    Portanto, não havia um "requisito" estrito para o new, mas sim seguir o padrão da linguagem da qual ele derivava mais fortemente.

    • 7
  2. ruakh
    2023-12-17T14:54:23+08:002023-12-17T14:54:23+08:00

    Sem new, por exemplo, fica claro que MyClass AnInstance = MyClass(AnArgument)cria um novo objeto.

    É mesmo?

    Considere esta classe (que é Java genuinamente válida):

    class ClientOfMyClass {
        // define a method named 'MyClass' that is not a constructor:
        static SubclassOfMyClass MyClass(final String arg) {
            return null;
        }
    
        String AnArgument = "hello";
        MyClass AnInstance = MyClass(AnArgument);
    }
    

    Nesse caso, MyClass(AnArgument)chama o método nomeado MyClassnesta classe e nunca cria uma instância de MyClass.

    Acho que seu erro está em pensar que essa new MyClass(AnArgument)é a sintaxe para chamar um construtor chamado MyClass. Eu diria que não. Em vez disso, é uma sintaxe para criar uma instância MyClasschamando um construtor apropriado. Acontece que a sintaxe para definir construtores envolve a repetição do nome da classe; mas não acho que devemos pensar nisso como o nome do construtor. Observe que nunca escrevemos, new MyClass.MyClass(AnArgument)mesmo que o construtor não esteja no escopo, e observe que isso new MyGenericClass<T>(AnArgument)passa Tcomo o argumento de tipo da classe MyGenericClass, não como seu construtor (já que os construtores não possuem parâmetros de tipo).

    • 6
  3. Best Answer
    rzwitserloot
    2023-12-17T15:28:05+08:002023-12-17T15:28:05+08:00

    É uma questão de namespaces.

    Em java, métodos e campos podem ter o mesmo nome e não estão totalmente relacionados. Na verdade, os tipos também podem, e os pacotes também. Todos os 4 são completamente ortogonais. Nunca os 4 se encontrarão :

    package foo;
    
    public class foo {
      int foo;
    
      public foo() { /* constructor */ }
    
      public void foo() { /* method */ }
    }
    

    Isso é totalmente legítimo. Nada substitui nada aqui - essa é uma classe nomeada fooem package foo, com 3 membros: um campo chamado foo, um construtor que aceita zero argumentos e um método nomeado fooque não aceita argumentos e não retorna nada. Você pode compilá-lo. Ele vai. Sem avisos. Seu IDE provavelmente reclamará que não é convencional iniciar um tipo com uma letra minúscula. Mas isso é apenas convenção. A especificação lang permite isso. javacirá compilar o acima perfeitamente.

    Então, se você pode ter todas essas coisas com o mesmo nome, como isso funciona?

    Do contexto, o java sempre sabe o que você está fazendo.

    Em algumas linguagens, os parênteses são opcionais ao invocar métodos, ou, pelo menos, tudo está no mesmo namespace.

    Por exemplo, em javascript:

    function test() {
    }
    
    var x = test;
    

    É legal; xagora é uma referência à testfunção.

    Isso também significa que você não pode , de fato, ter um método e uma variável com o mesmo nome em javascript:

    function test() {
    }
    
    test = 5;
    test();
    

    Não funciona. Essa última instrução tenta executar '5' como uma função que não é.

    Em java, esse não é o caso (esses parênteses não são opcionais e, sem os parênteses, simplesmente não se trata desse método, ponto final), porque java é único por ter 4 namespaces completamente não relacionados.

    Daí porque o new DEVE existir. Porque se não estivesse lá, java não saberia qual dos dois namespaces relevantes (tipos e métodos) explorar. Dito de forma diferente, isto:

    public class Test {
      public Test() {}
      public static void Test() {}
    }
    

    é java legal. Compila bem. Então, se importar esta classe Test e depois escrever: Test();, de qual eu estava falando?

    Em java, é claro: se você escrever new Test(), é o construtor, se você escrever Test(), é o método estático.

    Podemos debater longamente se foi uma ideia sábia ter namespaces ortogonais. No entanto, java não gosta de quebrar a compatibilidade com versões anteriores e, neste ponto , mudar tudo claramente não vale a pena a dor que causaria, então sua pergunta se resumiria a: "Por que os designers de java decidiram usar namespaces ortogonais 30 anos atrás", o que é difícil de responder em uma pergunta SO, eu precisaria de um chicote, um chapéu marrom e um pouco de música de John Williams.

    No nível da classe, esses construtores são compilados como métodos especiais, que agem principalmente como métodos estáticos (no sentido de que não fazem pesquisa virtual e não requerem um receptor - propriedades que ele compartilha com métodos estáticos e não com métodos de instância), nomeado <init>. Não Testou qualquer que seja o nome da sua classe.

    Então, é melhor pensar neles (pois é assim que funciona):

    • Construtores são construtores. Eles se associam ao tipo. Eles não têm nome .
    • Para escrever um construtor, você repete o nome do tipo e não adiciona nenhum tipo de retorno (nem mesmo void- ou você está declarando um método!) - mas isso é apenas para que o compilador saiba o que você está fazendo. Considere a repetição do nome do seu tipo como uma maneira de Java evitar a introdução de uma palavra-chave (poderia muito bem ter sido public constructor(String arg1, int arg2)em vez de public TypeNameGoesHere(String arg1, int arg2), mas não é. Novamente, 30 anos, evite algumas cobras, se quisermos nos aprofundar no porquê).

    NB: Os namespaces realmente se encontram. Está nas cadeias AST selecionadas: a.b.c.d.eé ambíguo: é aquele package a.b, então type c, com um tipo interno estático chamado d, que tem um campo estático chamado e? Ou é um pacote a, com classe b, classe interna c, campo estático d, que possui um tipo zque possui um campo de instância chamado e?

    Javac dá sua melhor facada no escuro durante a compilação e 'trava-o'. No nível de tempo de execução (arquivos de classe), realmente os namespaces não podem se encontrar. Cada instrução deixa claro a qual dos 4 namespaces um identificador está se referindo.

    • 6
  4. Ankit Kumar Maurya
    2023-12-17T14:43:46+08:002023-12-17T14:43:46+08:00

    Na minha opinião, o primeiro motivo é a sintaxe da linguagem java, é necessário utilizar a palavra-chave new para criação do objeto. Em segundo lugar, a palavra-chave tecnicamente nova invoca o construtor de uma classe para criar seu objeto e retornar. Desta forma nos permite usar construtores privados (para classes singleton) onde você não pode usar a palavra-chave new para a criação do objeto.

    • -1

relate perguntas

  • Lock Condition.notify está lançando java.lang.IllegalMonitorStateException

  • Resposta de microsserviço Muitos para Um não aparece no carteiro

  • Validação personalizada do SpringBoot Bean

  • Os soquetes Java são FIFO?

  • Por que não é possível / desencorajado definir um lado do servidor de tempo limite de solicitação?

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    destaque o código em HTML usando <font color="#xxx">

    • 2 respostas
  • Marko Smith

    Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}?

    • 1 respostas
  • Marko Smith

    Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)?

    • 2 respostas
  • Marko Smith

    Por que as compreensões de lista criam uma função internamente?

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Marko Smith

    java.lang.NoSuchMethodError: 'void org.openqa.selenium.remote.http.ClientConfig.<init>(java.net.URI, java.time.Duration, java.time.Duratio

    • 3 respostas
  • Marko Smith

    Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)?

    • 4 respostas
  • Marko Smith

    Por que o construtor de uma variável global não é chamado em uma biblioteca?

    • 1 respostas
  • Marko Smith

    Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto?

    • 1 respostas
  • Marko Smith

    Somente operações bit a bit para std::byte em C++ 17?

    • 1 respostas
  • Martin Hope
    fbrereto Por que a resolução de sobrecarga prefere std::nullptr_t a uma classe ao passar {}? 2023-12-21 00:31:04 +0800 CST
  • Martin Hope
    比尔盖子 Você pode usar uma lista de inicialização com chaves como argumento de modelo (padrão)? 2023-12-17 10:02:06 +0800 CST
  • Martin Hope
    Amir reza Riahi Por que as compreensões de lista criam uma função internamente? 2023-11-16 20:53:19 +0800 CST
  • Martin Hope
    Michael A formato fmt %H:%M:%S sem decimais 2023-11-11 01:13:05 +0800 CST
  • Martin Hope
    God I Hate Python std::views::filter do C++20 não filtrando a visualização corretamente 2023-08-27 18:40:35 +0800 CST
  • Martin Hope
    LiDa Cute Por que 'char -> int' é promoção, mas 'char -> short' é conversão (mas não promoção)? 2023-08-24 20:46:59 +0800 CST
  • Martin Hope
    jabaa Por que o construtor de uma variável global não é chamado em uma biblioteca? 2023-08-18 07:15:20 +0800 CST
  • Martin Hope
    Panagiotis Syskakis Comportamento inconsistente de std::common_reference_with em tuplas. Qual é correto? 2023-08-17 21:24:06 +0800 CST
  • Martin Hope
    Alex Guteniev Por que os compiladores perdem a vetorização aqui? 2023-08-17 18:58:07 +0800 CST
  • Martin Hope
    wimalopaan Somente operações bit a bit para std::byte em C++ 17? 2023-08-17 17:13:58 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve