Erros semânticos de Java | Por que o programador Java deve reconhecer erros semânticos

Mar 08 2023
Join JAVA FLAMES Muitas pessoas acham difícil de entender a diferença entre erros semânticos e erros sintáticos (sintaxe) no código Java, mas eles são diferentes. Você pode ver um erro semântico quando a sintaxe do seu código está correta, mas o uso do código não está correto.

Junte-se ao JAVA FLAMES

Muitas pessoas acham difícil entender a diferença entre erros semânticos e erros sintáticos (sintaxe) no código Java, mas eles são diferentes. Você pode ver um erro semântico quando a sintaxe do seu código está correta, mas o uso do código não está correto.

· O que é um erro semântico?
· Como os erros semânticos são detectados?
· Erros Semânticos Comuns

O que é um erro semântico?

Um erro semântico é um problema no seu código que impede o interpretador de entendê-lo. Pode não haver nada de errado com a lógica que você escreveu, mas fará com que o programa trave da maneira que você escreveu. Por exemplo, o código a seguir produzirá um resultado incorreto em um erro de tempo de execução semântico:

var a = 1 // No error
var b = 2 // No error
var c = 3 // No error
a + c = b

Erros semânticos são detectados em tempo de compilação e você pode considerá-los erros de análise estática. Por exemplo , se você tentar executar uma variável que não tenha declarado, ela gerará um erro semântico: Um erro semântico ocorre quando um programador escreve um código que não consegue comunicar o propósito pretendido. Isso é diferente de um erro de sintaxe, que ocorre quando o código está sintaticamente correto, mas não executa a tarefa projetada.

Em outras palavras, um erro semântico refere-se a um programa incorreto que produz um resultado que não faz sentido. Por exemplo , se um aplicativo meteorológico dissesse “Quente e ensolarado” mesmo quando estivesse chovendo lá fora, isso seria um erro semântico. O programa não produziu o que deveria produzir.

Como os erros semânticos são detectados?

alguns dos erros semânticos (os erros semânticos estáticos) são detectados pelo compilador, que gera uma mensagem indicando o tipo de erro e a posição no arquivo fonte Java onde ocorreu o erro (observe que o erro real pode ter ocorrido antes da posição sinalizado pelo compilador).

Neste ponto, descrevemos erros semânticos estáticos . Em cada caso, o compilador sinaliza um erro semântico estático quando um requisito da linguagem de programação não é satisfeito (tipos inválidos).

Existe outro tipo de problema: o que acontece se o seu programa compila e executa, mas não faz o que você queria? O computador está fazendo exatamente o que você programou, mas o que você programou estava errado. Esse é outro tipo de erro semântico: quando o programador usa incorretamente a linguagem de programação para resolver o problema.

Ao contrário de um erro semântico estático, um erro semântico dinâmico tem a ver com o significado. Se um programa contiver esse tipo de erro, ele será executado com sucesso, mas não produzirá o resultado correto.

A depuração não é tão fácil com um erro semântico. Vejamos um exemplo.

/**
 * This program prints the total benefit for the company
 * 
*/
public class TotalBenefit {
 public static void main(String[] args) {
  int branch1 = 250; 
        int branch2 = 500;
        System.out.println("The total benefit is  $" + (branch1 * branch2));
 }
}

Erros semânticos comuns

Erro de tipos incompatíveis

Este erro de sintaxe é muito comum em iniciantes. Em linguagens de programação compiladas como Java, você só pode atribuir valores a variáveis ​​compatíveis.

Compatível significa que eles têm o mesmo tipo ou têm tipos que podem ser convertidos automaticamente pelo compilador.

No exemplo abaixo, você pode ver que em Java não é possível atribuir um duplo a uma variável inteira. Algumas linguagens de programação podem fazer a conversão automaticamente, mas se você vir o erro abaixo, a correção é simples. Basta alterar o tipo da variável 'a' ou atribuir um valor inteiro em vez de duplo (5,5).

Esse tipo de erro semântico pode ser complicado porque o compilador sinalizará alguns erros e não outros. Por exemplo, se você tentar atribuir um float a uma variável int, o compilador exibirá uma mensagem de erro.

Por outro lado, se você atribuir um int a uma variável float, o compilador realizará uma conversão automática de tipo para int para torná-lo um float. O problema com este segundo cenário é que ele pode introduzir erros silenciosamente em seu código, especialmente se você realmente quis usar um float.

“variável <X> pode não ter sido inicializada”

Isso ocorre quando uma variável local declarada dentro de um método não foi inicializada. Pode ocorrer quando uma variável sem um valor inicial faz parte de uma instrução if.

int x;
if (condition) {
  x = 5;
}
System.out.println(x); // x may not have been initialized

É possível converter entre muitos tipos diferentes em Java. No entanto, não importa o quanto você queira converter um valor booleano em um int, o Java não permitirá que você faça isso. O conceito de executar a conversão está sintaticamente correto, mas você o está aplicando incorretamente, tornando isso um erro semântico que o compilador sempre detecta.

O erro “tipos inconversíveis” ocorre quando o código Java tenta realizar uma conversão ilegal.

TypeInvocationConversionTest.java:12: inconvertible types
found   : java.util.ArrayList<java.lang.Class<? extends TypeInvocationConversionTest.Interface1>>
required: java.util.ArrayList<java.lang.Class<?>>
lessRestrictiveClassList = (ArrayList<Class<?>>) classList;
                                                 ^

“variável não estática . . . não pode ser referenciado a partir de um contexto estático”

Este erro ocorre quando o compilador tenta acessar variáveis ​​não estáticas de um método estático

public class StaticTest {
private int count=0;
   public static void main(String args[]) throws IOException {
       count++; //compiler error: non-static variable count cannot be referenced from a static context
   }
}

  • Declare a variável como estática na assinatura.
  • Verifique o código, pois ele pode criar uma instância de um objeto não estático no método estático.

Esse problema ocorre quando o código Java tenta chamar um método não estático em uma classe não estática. Aqui está um exemplo:

class Sample {
  private int age;
  public void setAge(int a) {
    age=a;
  }
  public int getAge() {
    return age;
  }
  public static void main(String args[]) {
    System.out.println(“Age is:”+ getAge());
   }
  }

Exception in thread “main” java.lang.Error: Unresolved compilation problem:
Cannot make a static reference to the non–static method getAge() from the type Sample

Você obterá a mensagem “(array) <X> não inicializado” quando um array foi declarado, mas não inicializado. Arrays são fixos em comprimento, então cada array precisa ser inicializado com o comprimento desejado.

O seguinte código é aceitável:

AClass[] array = {object1, object2}
  As is:
       AClass[] array = new AClass[2];
       …
       array[0] = object1;
       array[1] = object2;
  But not:
       AClass[] array;
       …
       array = {object1, object2};

Esse problema ocorre quando os operadores são usados ​​para tipos, não em sua definição.

Os operadores são definidos apenas para determinados tipos, embora a conversão implícita de tipo seja permitida entre determinados tipos numéricos:

int a = 5; 
boolean b = true;
int c = a + b; // Error, can't add a boolean value double 
d = a + 1.4;  // OK, int is implicitly converted to double

Isso geralmente acontece quando o código Java tenta usar um tipo string em um cálculo. Para corrigi-lo, a string precisa ser convertida em inteiro ou float.

Possível perda de precisão

Às vezes, você pode aplicar o casting incorretamente. Por exemplo, converter um float para um int funciona bem, mas com a perda da parte decimal do número.

“Possível perda de precisão” ocorre quando mais informações são atribuídas a uma variável do que ela pode conter. Se isso acontecer, as peças serão jogadas fora. Se estiver correto, o código precisa declarar explicitamente a variável como um novo tipo.

Este erro surge ao tentar atribuir um valor de maior precisão a uma variável de menor precisão sem uma conversão de tipo explícito. Surpreendentemente, talvez, os literais de ponto flutuante sejam do tipo doublee você receberá esta mensagem se tentar atribuir um a uma variável do tipo float:

float sum = 0.0;  // Error, literal is not of type float

float sum = 0.0f;   // OK float sum = (float) 0.0;  // OK

Essa perda de precisão pode afetar a saída de seu aplicativo de maneiras inesperadas e fazer com que a saída reflita um valor diferente do esperado. O compilador nunca encontra esse tipo de erro porque você aplicou especificamente uma conversão à variável e o compilador espera que você saiba o que está fazendo.

Aplicando o escopo incorretamente

Qualquer variável que você declarar dentro de um método tem o mesmo escopo — visibilidade para outras partes do aplicativo, em outras palavras — do método. Conseqüentemente, você não pode declarar uma variável int estática privada dentro de um método. Em vez disso, você deve definir a variável globalmente assim:

public class PrivateVar
{
   // This declaration works.
   private static int PrivateInt = 3;
   public static void main(String[] args)
   {
      // This declaration doesn’t work.
      private static int PrivateInt = 3;
   }
}

Aqui estão alguns outros casos gerais de erros semânticos em Java

Incompatibilidades de tipo — Há várias maneiras de usar o tipo errado em C#. O exemplo acima é uma maneira. Aqui estão algumas outras maneiras possíveis:

  • Passando o tipo errado de valor para um método.
  • Retornando o tipo errado de valor de um método.
  • Configurando o tipo errado de valor em uma propriedade.
  • Configurando o tipo errado de valor em um campo.
  • Configurando o tipo errado de valor em uma variável local.
  • Usando um tipo em uma lista de argumentos genéricos que não está de acordo com as restrições de tipo genérico.
  • Passando o número errado de argumentos para uma chamada de método.
  • Passando o número errado de índices para uma matriz ou indexador.
  • Usando o número errado de argumentos de tipo genérico para um tipo ou método genérico.
  • Usando nomes indefinidos — Usando um namespace, tipo, método, campo, variável ou nome de propriedade que não existe.
  • Definindo dois tipos no mesmo namespace com o mesmo nome
  • Definir dois métodos na mesma classe com a mesma lista de argumentos e nome.
  • Definir uma propriedade, campo ou tipo aninhado que tem o mesmo nome de outra propriedade, campo ou tipo aninhado no mesmo tipo proprietário.
  • Definir duas variáveis ​​locais nos mesmos escopos ou descendentes com os mesmos nomes.

Apoie nossa publicação seguindo-a

Spring 3.0 e seus recursos Pergunta mais comum em entrevista baseada em Java8 Stream — Parte final Semáforo | Java Concurrent API Como o ChatGPT transformará o SEO: vantagens e desafios O que causa erros de sintaxe e como evitá-los | Como o compilador Java detecta erros de sintaxe … O guia completo para a construção de uma plataforma ICO de marca branca como um estranho me ajudou a entender a triste verdade da comunicação moderna A revolução da IA: a IA será o único autor em Médio? Eu não sabia que era um dos melhores escritores do Medium RestTemplate | FeignClient | WebClient com Spring Boot Como Criar um Projeto Quarkus Simples com Codificação de Integração de Banco de Dados: Nivele um array em Javascript Automatizando o Marketing de Mídia Social com ChatGPT 10 Widgets que Todo Desenvolvedor Flutter Deve Dominar