Para que servem os métodos ToString(), Equals() e GetHashCode()? \| TreinaWeb               Promoção no ar   Matricule-se agora e garanta **54% de desconto**  

  Termina em   Tempo restante da oferta: 11 Horas 

 49 Min 

 11 Seg 

   Tempo restante da oferta: 11 49 11 

  [Assinar →](https://www.treinaweb.com.br/checkout/pagamento/plano/anual?cupom=TW-SCLIENTE26) 

   [                ](https://www.treinaweb.com.br)  Explorar  

 [ Quanto custa? ](#assinatura) [ FAQ ](https://www.treinaweb.com.br#faq) [Matricule-se](#assinatura) [ Entrar ](https://www.treinaweb.com.br/login) 

     [ Início ](https://www.treinaweb.com.br) [ Artigos ](https://www.treinaweb.com.br/blog) Para que servem os métodos ToString(), Equals() e GetHashCode()?  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

# Para que servem os métodos ToString(), Equals() e GetHashCode()?

 Neste artigo vamos entender como funcionam e para que servem os métodos ToString(), Equals() e GetHashCode() em linguagens baseadas no .NET e no Java.

 [ Cleber Campomori ](https://www.treinaweb.com.br/blog/autor/cleber-campomori) 10 anos atrás

  ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2021/05/tostring.jpg)  

Muitas pessoas costumam se confundir com três métodos que qualquer classe possui no .NET e no Java: os métodos `ToString()`, `Equals()` e `GetHashCode()`. Os dois primeiros são mais ou menos claros até certo ponto, mas o último vive causando confusão e pânico entre desenvolvedores [Java](https://www.treinaweb.com.br/blog/o-que-e-e-como-comecar-com-java/ "Java") e [C# (Sharp)](https://www.treinaweb.com.br/blog/o-que-e-e-como-comecar-com-c-sharp/ "C# (Sharp)"), ainda mais na hora em que necessitamos sobrescrevê-los… Que tal entendermos de uma vez por todas para que estes três métodos servem?

**Importante:** os conceitos que veremos aqui servem tanto para a plataforma Java quanto para a plataforma .NET! :D

[  ![C# (C Sharp) - Introdução ao ASP.NET Core](https://d2knvm16wkt3ia.cloudfront.net/assets/svg-icon/csharp.svg)   Curso C# (C Sharp) - Introdução ao ASP.NET Core Conhecer o curso ](https://www.treinaweb.com.br/curso/csharp-avancado-introducao-ao-aspnet-core)

##### Por que toda classe tem estes métodos?

No Java e no .NET, toda classe tem um ancestral por “padrão”: a classe `Object`. Dessa maneira, qualquer objeto de qualquer classe que criarmos em Java ou .NET, pelo *Princípio da Substituição de Liskov*, também será uma instância de `Object`. E a classe `Object` já expõe por padrão pelo menos os três métodos que estão em discussão.

![Diagrama de classe](https://d2m498l008ebpa.cloudfront.net/2016/12/Class_Object.png)

[  ![Java - Fundamentos](https://d2knvm16wkt3ia.cloudfront.net/assets/svg-icon/java.svg)   Curso Java - Fundamentos Conhecer o curso ](https://www.treinaweb.com.br/curso/java-fundamentos)

##### O método ToString()

Talvez este seja o método que é mais claro com relação ao seu propósito. Seu objetivo é trazer uma representação textual de uma instância de um objeto. Essa representação textual de um objeto vem a ser muito útil principalmente em situações de *debugging* e de *logging*. Isso ocorre porque os métodos de saída para o *streamming* padrão (os famosos `System.out.print[ln]()` ou `Console.Write[Line]()`), assim como os principais métodos de praticamente todas as APIs de *log* (métodos como o `debug()` e `info()`) sempre chamam por padrão o método `ToString()` de instâncias de objetos que tenham sido passadas para eles.

O exemplo abaixo está escrito em C#, mas o princípio é exatamente o mesmo para o Java também, rs.

Imagine o código abaixo:

```csharp
namespace TreinaWeb.Exemplo
{
    public class Pessoa
    {
        public string Nome { get; set; }
    }
}
// ...
Pessoa p = new Pessoa { Nome = "TreinaWeb" };
Console.WriteLine(p);
// ou
Console.WriteLine(p.ToString());

```

Perceba que não foi realizada nenhuma sobrecarga do método `ToString()`, o que faz com que a chamada deste método para a classe `Pessoa` encaminhe a chamada para a classe ancestral, ou seja: na verdade será chamado o método `Object.ToString()`.

> Não se esqueça: ==todo e qualquer objeto/classe sempre vai ter o método `ToString()` por causa da herança da classe `Object`==. Se a própria classe não implementa este método, a chamada será encaminhada para o `ToString()` “padrão”, ou seja, o método `ToString()` da classe `Object`.

No caso do C#, a saída do código abaixo seria a representada abaixo, independente da chamada explícita ao método `ToString()` ou não:

```dos
TreinaWeb.Exemplo.Pessoa

```

A saída tanto para a chamada explícita ao método `ToString()` como para a chamada ocultando-se a chamada é a mesma. Isso ocorre porque os método `Console.Write[Line]()` chama o método `ToString()` da instância repassada como parâmetro por padrão. ;)

O que o .NET emite como saída nesses casos é um elemento conhecido como *Full Qualified Name*, ou simplesmente *FQN*. Apesar de o nome assustar, ele é muito simples: trata-se somente do “nome completo” e único da classe, que é composto por *namespace* + nome da classe.

Se tivéssemos o código equivalente em Java, teríamos uma saída similar à abaixo:

```dos
TreinaWeb.Exemplo.Pessoa@1033203

```

A saída é muito similar ao *FQN* do .NET, com o acréscimo deste número precedido por `@`. Costumam dizer por aí que este número logo após o `@` é a posição de memória do objeto. Daqui a pouco vamos ver que não é “beeem” assim, hehe.

O grande ponto é que essa saída fornecida pelo método `ToString()` não tem nenhuma utilidade prática para nós, tanto no *streamming* padrão de saída, quanto em um arquivo de *log*. Daí vem a necessidade da sobrescrita deste método.

A idéia é que o método `ToString()` forneça uma representação simplificada e direta do estado do objeto em questão. Uma maneira de atingir este objetivo é fazer com que a saída forneça o valor atual dos atributos do objeto.

Poderíamos sobrescrever o método `ToString()` da nossa classe `Pessoa` da seguinte maneira:

```csharp
namespace TreinaWeb.Exemplo
{
    public class Pessoa
    {
        public string Nome { get; set; }

        public override string ToString()
        {
            return string.Format("Pessoa [Nome = {0}]", this.Nome);
        }
    }
}

```

Nossa saída agora, tanto em Java quanto em .NET, seria a mesma abaixo:

```dos
Pessoa [Nome = TreinaWeb]

```

Agora temos uma representação “palpável” e que faça sentido para nós. Essa é com certeza uma representação muito melhor do que as representações padrão da classe `Object`.

##### O método Equals()

Antes de falarmos do método `Equals()`, precisamos relembrar um pouco sobre manipulação de memória, principalmente sobre *stack* e *heap*.

> Se você quer relembrar como funciona a manipulação de memória, tanto em Java quanto em .NET, você pode ver [este nosso artigo](https://www.treinaweb.com.br/blog/gerenciamento-de-memoria-no-c-stack-heap-value-types-e-reference-types/), onde tratamos sobre manipulação de memória, *stack*, *heap*, *value-types* e *reference-types*.

Quando criamos um objeto da classe `Pessoa`, este objeto será armazenado na memória *heap*:

```csharp
Pessoa minhaPessoa = new Pessoa();

```

![Alocação de memória: reference-type](https://treinaweb-suporte.s3.amazonaws.com/imagens/tpuCNc7AAloca%C3%A7%C3%A3o_Mem%C3%B3ria_Reference_Type.png)

Não se esqueça de que o compilador não acessa os objetos na *heap* de maneira direta por questões de performance. Sendo assim, o acesso a esse objeto armazenado na *heap* é feito através de uma **referência** dentro da *stack* para o objeto *minhaPessoa*, apontando onde na memória *heap* que este objeto está de fato guardado! Sim: estamos falando de ponteiros.

![Acesso à memória: reference-types](https://treinaweb-suporte.s3.amazonaws.com/imagens/BH7wMTvVCompilador_Acessando_Mem%C3%B3ria_Reference_Type.png)

É importante entendermos estes conceitos para entendermos melhor como o método `Equals()` funciona.

Quando comparamos objetos, é considerada uma boa prática utilizarmos o método `Equals()` para fazer a comparação de igualdade. E, quando a classe a qual os objetos em questão pertencem não sobrescreve o método `Equals()`, o método `Object.Equals()` será chamado.

Vamos verificar o código abaixo, considerando ainda a classe `Pessoa`:

```csharp
namespace TreinaWeb.Exemplo
{
    public class Pessoa
    {
        public string Nome { get; set; }
    }
}
// ...
Pessoa p = new Pessoa { Nome = "TreinaWeb" };
Pessoa p2 = new Pessoa { Nome = "TreinaWeb" }; 

Console.WriteLine(p.Equals(p2));

```

Faria muito sentido se esse código fornecesse como saída `true`, afinal, os objetos aparentemente são iguais, certo? Mas esse código irá produzir `false`, apesar de o nome nos dois objetos serem iguais… Por que isso acontece?

Aí entra em cena a relação entre o método `Object.Equals()` e a maneira como a memória é manipulada no Java e no .NET.

A cada vez que utilizamos a keyword `new`, nós estamos instruindo o compilador a reservar um espaço na memória *heap* e criar um ponteiro na *stack* para que seja possível acessar esta área da *heap*. Sendo assim, no código acima, são criadas duas áreas de memória na *heap* distintas. Estas áreas são gerenciadas, respectivamente, pelos ponteiros `p` e `p2`.

O que ocorre quando utilizamos o `Equals()` baseado na implementação de `Object.Equals()` é que este por padrão verifica se os ponteiros ==**apontam para a mesma área de memória na *heap*!**== Como temos dois objetos instanciados de maneira distintas (chamamos o `new` para cada um dos ponteiros), nós temos também duas posições de memória distintas para cada um dos objetos `p` e `p2`. Por isso, por padrão, temos como resposta `false` para o código acima.

Agora, vamos imaginar o código abaixo:

```csharp
namespace TreinaWeb.Exemplo
{
    public class Pessoa
    {
        public string Nome { get; set; }
    }
}
// ...
Pessoa p = new Pessoa { Nome = "TreinaWeb" };
Pessoa p2 = p; 

Console.WriteLine(p.Equals(p2));

```

Agora sim! Perceba que para `p2` nós não instruímos o compilador a criar uma nova área de memória na `heap`, e sim o instruímos a fazer com que `p2` aponte para a mesma posição de memória na *heap* para a qual `p` aponta. Desta maneira, neste último código, obteremos `true` como resposta quando utilizamos a implementação do método `Equals()` baseada em `Object.Equals()`.

Agora, não faz muito sentido para nós esta implementação do método `Equals()` baseado em `Object.Equals()`. Para nós, faria muito mais sentido que o método `Equals()` na primeira situação deste tópico retornasse `true`, afinal, ambos os objetos `Pessoa` possuem o mesmo nome. Por isso, é importantíssimo para nós sobrescrevermos de maneira adequada o método `Equals()`.

Antes de partirmos para a sobrecarga, é importante entendermos algumas premissas para o método `Equals()`:

- Se ambos os objetos que estão sendo comparados apontam para a mesma posição de memória, é mandatório que `Equals()` retorne `true`, baseado na implementação de `Object.Equals()`;
- `x.Equals(x)` sempre tem que retornar `true`;
- `x.Equals(y)` sempre tem que retornar o mesmo que `y.Equals(x)`. Este princípio é conhecido como *princípio de simetria*;
- Se `x.Equals(y)` e `y.Equals(z)`, `z.Equals(x)` tem que retornar `true` também. Isso ocorre por decorrência do *princípio da simetria*;
- `x.Equals(null)` sempre será falso. O método `Equals()` por definição não pode retornar exceções do tipo `NullReferenceException` ou `NullPointerException`. Isso faz sentido: se um ponteiro é nulo, na verdade ele não aponta para nenhuma área da *heap* e, portanto, é impossível fazer uma comparação coerente entre os objetos.

Tendo todos estes princípios em vista, temos 3 pontos importantes a serem observados quando sobrescrevermos o método `Equals()` para que este atenda a todos estes requisitos:

- Precisamos ver se um dos participantes da chamada do método `Equals()` é nulo;
- Precisamos ver se os dois objetos apontam para a mesma área de memória;
- Precisamos comparar o estado interno dos participantes da chamada do `Equals()`.

Poderíamos sobrescrever o método `Equals()` da nossa classe `Pessoa()` da seguinte maneira, afim de que a nossa sobrecarga atenda aos requisitos essenciais:

```csharp
namespace TreinaWeb.Exemplo
{
    public class Pessoa
    {
        public string Nome { get; set; }

        public override bool Equals(Object obj)
        {
            // Verificando se o segundo participante está nulo
            if (obj == null)
            {
                return false;
            }
            Pessoa p2 = obj as Pessoa;
            // Verificando se o cast foi realizado com sucesso. 
            // Caso não foi, obj nem é um objeto do tipo Pessoa 
            // e automaticamente o método tem que retornar false
            // NOTA: o operador de cast "as" retorna
            // null caso o cast não seja possível
            if (p2 == null)
            {
                return false;
            }
            // Vamos agora verificar se ambos apontam para a mesma posição 
            // de memória utilizando Object.Equals()
            if (base.Equals(obj))
            {
                return true;
            }
            // Agora comparamos o estado interno dos objetos!
            return this.Nome == p2.Nome;
        }
    }
}

```

Agora nós temos o método `Equals()` devidamente sobrescrito e respeitando todas as condições necessárias. Considerando esta sobrecarga, se chamarmos o código abaixo…

```csharp
Pessoa p = new Pessoa { Nome = "TreinaWeb" };
Pessoa p2 = new Pessoa { Nome = "TreinaWeb" }; 
Pessoa p3 = p2;

Console.WriteLine(p.Equals(p2));
Console.WriteLine(p2.Equals(p3));
Console.WriteLine(p.Equals(p3));

```

… obteremos `true` em todas as saídas, o que faz muito sentido!

No caso específico do C#, nós ainda poderíamos utilizar `p == p2`, o que causaria também a chamada de `Object.Equals()`. Por isso, no C#, temos a possibilidade de fazermos a sobrescrita também de operadores. Nesta situação, precisaríamos sobrescrever o operador `==` para a classe `Pessoa` para que tenhamos tudo “nos trilhos” e não tenhamos duas implementações distintas de igualdade. Da mesma maneira, acaba sendo prudente sobrescrever também o operador `!=`. Nosso código poderia ficar como está abaixo:

```csharp
namespace TreinaWeb.Exemplo
{
    public class Pessoa
    {
        public string Nome { get; set; }

        public static bool operator ==(Pessoa a, Pessoa b)
        {
            // Fazemos o cast para Object
            // para evitar StackOverFlowException:
            // o código cairia em loop infinito
            // chamando de maneira encadeada
            // o método Equals() sobrescrito
            // e o operador == sobrescrito! ;)
            if ((((object)a) == null) || (((object)b) == null))
            {
                return false;
            }
            return object.Equals(a, b) || a.Nome == b.Nome;
        }

        public static bool operator !=(Pessoa a, Pessoa b)
        {
            return !(a == b);
        }

        public override bool Equals(Object obj)
        {
            // Verificando se o segundo participante está nulo
            if (obj == null)
            {
                return false;
            }
            Pessoa p2 = obj as Pessoa;
            // Verificando se o cast foi realizado com sucesso. 
            // Caso não foi, obj nem é um objeto do tipo Pessoa 
            // e automaticamente o método tem que retornar false
            if (p2 == null)
            {
                return false;
            }
            // Vamos agora verificar se ambos apontam 
            // para a mesma posição de memória utilizando Object.Equals()
            if (base.Equals(obj))
            {
                return true;
            }
            // Agora comparamos o estado interno dos objetos!
            return this.Nome == p2.Nome;
        }
    }
}

```

##### O método GetHashCode() ou hashCode()

Por fim, temos o famigerado método `GetHashCode()` ou `hashCode()`. Este é um dos métodos que causam mais confusão nos desenvolvedores.

O *hash code* é um número inteiro que é gerado de maneira única para cada objeto que esteja alocado em memória. É como se ele fosse um ID único para cada objeto que esteja sob domínio da *CLR* ou da *JVM*.

E onde este código único é utilizado? Aí é a grande sacada! Ele é utilizado principalmente dentro de coleções com a finalidade de melhoria da performance. A *JVM* e a *CLR* utilizam o *hash code* internamente para localizar objetos em coleções de maneira mais rápida. E daí também vem sua relação direta com o método `Equals()`.

Uma das maneiras que os ambientes de execução do .NET e do Java utilizam para ver se um determinado objeto existe dentro de uma coleção é comparando os *hash codes* dos objetos pertencentes à coleção com o *hash code* do objeto a ser localizado. E, se um objeto é localizado dentro de uma coleção, é porque ele é **igual** ao elemento dentro de alguma posição da coleção em questão. Percebe a relação entre `GetHashCode()` e `Equals()`?

Por isso, vale a máxima abaixo para o método `GetHashCode()`:

> Se `x.Equals(y)` e `x` e `y` são objetos da mesma classe, `x.GetHashCode() == y.GetHashCode()` tem que obrigatoriamente retornar `true`.

A sobrescrita do `Equals()` impacta diretamente na implementação do `GetHashCode()` e vice-versa por causa dessa relação entre os dois. E é por isso que as IDEs emitem *warnings* quando você, por exemplo, sobrescreve o método `Equals()` e não sobrescreve o método `GetHashCode()` e vice-versa.

Agora, um ponto interessante: nem a *CLR* e nem a *JVM* garantem a situação inversa! Isso quer dizer que dois objetos, deste que de tipos (ou classes) diferentes, podem por coincidência retornar o mesmo *hash code*!

> Se `x` é do tipo `A` e `y` é do tipo `B` (ou seja: `x` e `y` são objetos de classes diferentes), `x.Equals(y)` irá retornar por definição `false`; porém, pode ser que `x.GetHashCode() == y.GetHashCode()` retorne `true`.

Essa situação, apesar de ser incomum, pode acontecer. Ela é chamada de ***colisão***. A colisão, quando ocorre, geralmente acontece por causa de sobrescrita equivocada do método `GetHashCode()`.

O método padrão `Object.GetHashCode()` tem uma implementação um pouco complexa. Se estivermos falando de .NET, a chamada a `Object.GetHashCode()` irá ser convertida para uma chamada de baixo nível para `ObjectNative::GetHashCode`. Se estivermos falando de Java, a chamada de `Object.hashCode()` irá converter a posição de memória onde o objeto está alocado para uma representação numérica, adotando esta representação como sendo o *hash code*. Inclusive, lembra-se da implementação padrão do método `toString()` no Java? Pois então… Aquele número estranho que vem depois do *@* é o *hash code* do objeto! =)

Existe um outro ponto muito importante com relação ao método `GetHashCode()`:

> Se `GetHashCode()` tem relação direta com `Equals()`, um mesmo objeto sempre deverá retornar o mesmo *hash code*, da mesma maneira que seu método `Equals()` sempre retornará o mesmo resultado quando haver uma comparação entre dois objetos.

Aí entra um problema grave: a implementação padrão vinda de `Object.GetHashCode()` não retorna o mesmo *hash code* para o mesmo objeto. Na verdade, a cada chamada ao método padrão `Object.GetHashCode()`, um novo *hash code* será invocado. Isso faz cair por terra o ganho de performance que a utilização de `GetHashCode()` poderia trazer… Daí vem a necessidade de sobrescrevermos corretamente este método em nossas classes.

Uma técnica geralmente utilizada para conseguirmos sobrescrever corretamente o método `GetHashCode()` é somar os *hash codes* de todos os atributos da classe e multiplicar por um número primo. Isso reduz bastante as chances de haver algum tipo de colisão.

Sendo assim, poderíamos sobrescrever o método `GetHashCode()` da classe `Pessoa` da seguinte maneira:

```csharp
namespace TreinaWeb.Exemplo
{
    public class Pessoa
    {
        public string Nome { get; set; }

        public override int GetHashCode()
        {
            // 17 é um número primo! ;)
            return this.Nome.GetHashCode() * 17;
        }
    }
}

```

O método `GetHashCode()` auxilia na performance dentro de coleções porque é muito mais simples para os compiladores comparar dois números inteiros do que chamar o método `Equals()` para cada elemento que faça parte da coleção, sendo que a implementação do `Equals()` pode ser um pouco complexa e lenta.

Sendo assim, quando o compilador precisa localizar um objeto dentro de uma coleção, ele faz uma iteração em cada elemento que faça parte e faz a comparação com o objeto a ser localizado da seguinte maneira:

- A primeira comparação é feita através do *hash code* dos objetos envolvidos. Se eles forem diferentes, o compilador para o trabalho por aqui, já que se dois objetos são iguais (ou seja, o método `Equals()` com os dois objetos deveria retornar `true`), o *hash code* de ambos também deveria ser igual;
- Caso os *hash codes* sejam iguais, o compilador levanta a hipótese de estar havendo uma colisão. Então, ele chama o método `Equals()` para confirmar se os objetos são iguais ou não. Se eles forem iguais, o compilador considera que encontrou o objeto dentro da coleção. Caso não, o compilador avança para o próximo item da coleção e reinicia o processo de comparação.

Consegue perceber como o *hash code* pode acelerar o processo de manipulação de coleções? Ele ajuda o compilador a evitar a chamada ao método `Equals()`, que pode ser lento, de maneira desnecessária! o/

O método `GetHashCode()` é importantíssmo para coleções. Desde coleções mais básicas, como `ArrayList`; até coleções mais complexas, como `Dictionary` ou `Map`, se utilizam deste método. O `Dictionary`, inclusive, utiliza este método para localizar se existem chaves duplicadas ou não.

##### Os métodos ToString(), Equals() e GetHashCode() são importantíssimos!

Esperamos que você tenha percebido melhor a importância desses métodos para os desenvolvedores. Muitos costumam não dar a devida importância para a sobrescrita correta destes métodos, o que pode ocasionar problemas bem críticos no código em determinadas situações (principalmente quando falamos de serialização de objetos e ambientes de alta concorrência). Você, inclusive, pode acompanhar um problema decorrente da sobrescrita e utilização incorretas destes métodos em um ambiente real [neste post do StackOverflow](http://stackoverflow.com/questions/638761/gethashcode-override-of-object-containing-generic-array/639098#639098).

Tem alguma dúvida? Quer discutir sobre algum determinado ponto? Quer expor uma situação pela qual você já passou no seu dia-a-dia como desenvolvedor que envolvia a utilização destes métodos? Compartilha com a gente nos comentários! Vamos discutir sobre este assunto! o/

Até o próximo post! =)

[  ![Desenvolvedor ASP.NET Full-Stack](https://d2knvm16wkt3ia.cloudfront.net/assets/svg-icon/csharp.svg)   Formação Desenvolvedor ASP.NET Full-Stack Conhecer a formação ](https://www.treinaweb.com.br/formacao/desenvolvedor-aspnet-full-stack)

- [ #.NET ](https://www.treinaweb.com.br/blog/tag/dotnet)
- [ #Arquitetura de Software ](https://www.treinaweb.com.br/blog/tag/arquitetura-de-software)
- [ #Orientação a objetos ](https://www.treinaweb.com.br/blog/tag/orientacao-a-objetos)
- [ #Java ](https://www.treinaweb.com.br/blog/tag/java)

Autor

 ![Cleber Campomori](//secure.gravatar.com/avatar/c659c6a58478cad5b7751370ba94205f?d=mm)

## Cleber Campomori

 Líder de Conteúdo/Inovação. Pós-graduado em Projeto e Desenvolvimento de Aplicações Web. Certificado Microsoft MCSD (Web). 

 [Todos os artigos](https://www.treinaweb.com.br/blog/autor/cleber-campomori)  

## Continue estudando

 Transforme leitura em prática com os cursos e formações da TreinaWeb.

 [Ver cursos](https://www.treinaweb.com.br/cursos)   

  Continue lendo

## Artigos relacionados

- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2021/01/como-instalar-o-java-e-nosso-primeiro-exemplo-400x280.png)  [ Desenvolvimento Back-end ](https://www.treinaweb.com.br/blog/categoria/desenvolvimento-back-end) 

     4 anos atrás

    ##  [ Conheça o recurso de Records no Java ](https://www.treinaweb.com.br/blog/conheca-o-recurso-de-records-no-java) 

     Neste artigo, vamos aprender sobre o recurso de Records no Java. Veremos como utilizar esse recurso, suas vantagens e desvantagens.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2022/01/criando-uma-api-com-spring-data-jpa-e-spring-web-400x280.png)  [ Desenvolvimento Back-end ](https://www.treinaweb.com.br/blog/categoria/desenvolvimento-back-end) 

     5 anos atrás

    ##  [ Criando uma API com Spring Data JPA e Spring Web ](https://www.treinaweb.com.br/blog/criando-uma-api-com-spring-data-jpa-e-spring-web) 

     Neste artigo vamos aprender como criar uma API com persistência de dados utilizando o Spring Web MVC e o Spring Data JPA.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2022/01/iniciando-com-spring-data-jpa-400x280.png)  [ Desenvolvimento Back-end ](https://www.treinaweb.com.br/blog/categoria/desenvolvimento-back-end) 

     5 anos atrás

    ##  [ Iniciando com Spring Data JPA ](https://www.treinaweb.com.br/blog/iniciando-com-spring-data-jpa) 

     Neste artigo iremos conhecer o Spring Data JPA, entender o seu funcionamento e como o mesmo pode nos auxiliar na camada de persistência.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2019/08/14131229/HEALTH-CHECKS-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     7 anos atrás

    ##  [ Verificando a integridade da aplicação ASP.NET Core com Health Checks ](https://www.treinaweb.com.br/blog/verificando-a-integridade-da-aplicacao-asp-net-core-com-health-checks) 

     Verificar e monitorar a integridade de uma aplicação web é algo essencial, principalmente em ambientes distribuídos. O ASP.NET Core facilita esta tarefa através de Health Checks, como você verá neste artigo.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/01/05103838/SIGNALR-400x280.png)  [ C# ](https://www.treinaweb.com.br/blog/categoria/csharp) 

     7 anos atrás

    ##  [ Aplicações em tempo real com ASP.NET Core SignalR ](https://www.treinaweb.com.br/blog/aplicacoes-em-tempo-real-com-asp-net-core-signalr) 

     Aprenda como criar uma streaming api utilizando a biblioteca de aplicações em templo real, SignalR.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2019/02/01143234/PROVEDORES-LOG-400x280.png)  [ Desenvolvimento Back-end ](https://www.treinaweb.com.br/blog/categoria/desenvolvimento-back-end) 

     7 anos atrás

    ##  [ Switch Expressions no C# 8.0 ](https://www.treinaweb.com.br/blog/switch-expressions-no-c-8-0) 

     Obtenha uma visão geral do recurso switch expressions do C# 8.0 e aprenda a criar códigos mais limpos e legíveis nesta versão da linguagem.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2019/10/20234042/capa-dart-400x280.png)  [ Dart ](https://www.treinaweb.com.br/blog/categoria/dart) 

     5 anos atrás

    ##  [ Como utilizar generics no Dart ](https://www.treinaweb.com.br/blog/como-utilizar-generics-no-dart) 

     Neste artigo vamos aprender sobre os Generics na linguagem Dart e como eles podem nos auxiliar em garantir que os tipos dos objetos sejam o que esperamos que eles sejam.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/09/ux-research-e-360-view-o-que-e-e-como-pode-ser-aplicado-400x280.png)  [ Acessibilidade e User Experience (UX) ](https://www.treinaweb.com.br/blog/categoria/acessibilidade-e-user-experience-ux) 

     6 anos atrás

    ##  [ UX Research e 360 View – O que é e como pode ser aplicado? ](https://www.treinaweb.com.br/blog/ux-research-e-360-view-o-que-e-e-como-pode-ser-aplicado) 

     Entenda o que é e como aplicar o UX Research e 360 View, técnicas importantes na hora de pensar em uma melhor experiência do usuário.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2022/08/MEDIA-QUERIES-400x280.png)  [ CSS ](https://www.treinaweb.com.br/blog/categoria/css) 

     4 anos atrás

    ##  [ Media queries, o que são e como usar no CSS? ](https://www.treinaweb.com.br/blog/media-queries-o-que-sao-e-como-usar-no-css) 

     Neste artigo, nós iremos aprender sobre o uso de media queries no CSS e iremos aprender como utilizá-los em nossas aplicações web.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2020/07/CLASSES-ABSTRATAS-INTERFACES-400x280.png)  [ Desenvolvimento ](https://www.treinaweb.com.br/blog/categoria/desenvolvimento) 

     6 anos atrás

    ##  [ Classes Abstratas vs Interfaces ](https://www.treinaweb.com.br/blog/classes-abstratas-vs-interfaces) 

     Veja neste artigo o que são e quais as diferenças entre classes abstratas e interfaces.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2019/05/24102227/laravel-request-400x280.png)  [ PHP ](https://www.treinaweb.com.br/blog/categoria/php) 

     8 anos atrás

    ##  [ Principais métodos para obtenção de parâmetros da Request no Laravel ](https://www.treinaweb.com.br/blog/principais-metodos-para-obtencao-de-parametros-da-request-no-laravel) 

     Aprenda nesse artigo como obter dados enviados na requisição. Veremos desde como pegar a instância da Request até métodos avançados para obtenção de parâmetros passados via GET, POST e como trabalhar com arquivos.

     Ler artigo
- ![](https://dkrn4sk0rn31v.cloudfront.net/uploads/2018/07/31131011/funções-js-400x280.png)  [ Javascript ](https://www.treinaweb.com.br/blog/categoria/javascript) 

     8 anos atrás

    ##  [ JavaScript: métodos de Arrays que você precisa conhecer ](https://www.treinaweb.com.br/blog/javascript-metodos-de-arrays-que-voce-precisa-conhecer) 

     Trabalha com JavaScript? Então você precisa conhecer estes métodos para trabalhar com Arrays.

     Ler artigo

## Um ano de acesso total para você viver de programação.

 Todos os cursos e formações da TreinaWeb numa única assinatura, com professores que atuam no mercado, suporte direto e certificados. Do primeiro `console.log` ao mercado de trabalho.

- **1 ano** de acesso a **todos os cursos**
- Cursos novos **toda semana**
- Suporte **direto com professores**
- Plano de carreira **personalizado**
- **Certificados digitais** inclusos
- **Aplicativos** para Android e iOS, com **acesso offline**

    **Garantia incondicional de satisfação** 

 Teste por 7 dias e, se não fizer sentido para você, devolvemos seu dinheiro.

### Acesso completo a todos os cursos e dezenas de Formações.

 12 meses 

  Economize R$ 840,00  54% OFF 

 de 12x R$ 129,00 por apenas

 12x  R$ 59,00

 sem juros no cartão de crédito ou R$ 599,00 à vista

  Oferta termina em  **11h 49min 11s**

- Acesso imediato e ilimitado durante 1 ano.
- Plano de carreira personalizado.
- Suporte direto com professores.
- E muito mais!

 [Matricule-se agora](https://www.treinaweb.com.br/checkout/pagamento/plano/anual?cupom=TW-SCLIENTE26)

     [                ](https://www.treinaweb.com.br)

 Escola online de programação, tecnologia e IA.

- [  ](https://www.facebook.com/TreinaWeb/)
- [  ](https://www.instagram.com/treinaweb/)
- [  ](https://www.youtube.com/user/TreinaWeb)
- [  ](https://twitter.com/treinaweb)
- [  ](https://www.linkedin.com/company/treinaweb)
- [  ](https://github.com/treinaweb)

## Inscreva-se em nossa newsletter

Receba lançamentos, promoções e novidades.

   Seu nome     Seu WhatsApp     Seu melhor e-mail   Inscrever-se 

## Cursos

- [ Base para Devs ](https://www.treinaweb.com.br/categoria/base-para-devs)
- [ Front-end ](https://www.treinaweb.com.br/categoria/desenvolvimento-front-end)
- [ Back-end ](https://www.treinaweb.com.br/categoria/desenvolvimento-back-end)
- [ Mobile ](https://www.treinaweb.com.br/categoria/desenvolvimento-mobile)
- [ Bancos de Dados ](https://www.treinaweb.com.br/categoria/bancos-de-dados)
- [ Cloud ](https://www.treinaweb.com.br/categoria/cloud-computing)
- [ IA ](https://www.treinaweb.com.br/categoria/ia)
- [ E mais ](https://www.treinaweb.com.br/categoria/e-mais)
- [ Ver todos os cursos ](https://www.treinaweb.com.br/cursos)

## Conteúdo

- [ Formações ](https://www.treinaweb.com.br/formacoes)
- [ Projetos práticos ](https://www.treinaweb.com.br/projetos-praticos)
- [ Direto ao ponto ](https://www.treinaweb.com.br/direto-ao-ponto)
- [ Planos ](https://www.treinaweb.com.br#assinatura)
- [ Depoimentos ](https://www.treinaweb.com.br#depoimentos)
- [ Comunidade ](https://www.treinaweb.com.br#comunidade)
- [ Corpo docente ](https://www.treinaweb.com.br#docente)

## A empresa

- [ Sobre a TreinaWeb ](https://www.treinaweb.com.br#sobre)
- [ Perguntas frequentes ](https://www.treinaweb.com.br#faq)
- [ Vantagens de estudar na TreinaWeb ](https://www.treinaweb.com.br/vantagens-de-estudar-na-treinaweb)
- [ Cursos para empresas ](https://www.treinaweb.com.br/empresas)
- [ Sugira um novo curso ](https://www.treinaweb.com.br/sugerir-curso)
- [ Trabalhe conosco ](https://www.treinaweb.com.br/trabalhe-conosco)
- [ Artigos ](https://www.treinaweb.com.br/blog)
- [ Desenvolvedores e agentes ](https://www.treinaweb.com.br/developers)
- [ Contato ](https://www.treinaweb.com.br/contato)
- [ Política de privacidade ](https://www.treinaweb.com.br/politica-de-privacidade)
- [ Termos de uso ](https://www.treinaweb.com.br/termos-de-uso)

## Baixe nosso aplicativo

 [   Disponível na **App Store**  ](https://apps.apple.com/us/app/treinaweb/id1322729447) [   Disponível no **Google Play**  ](https://play.google.com/store/apps/details?id=br.com.treinaweb.mobile) 

  Av. Paulista, 1765, Conj 71 e 72 · Bela Vista · São Paulo · SP · 01311-200   © 2004 – 2026 TreinaWeb Tecnologia LTDA · CNPJ 06.156.637/0001-58
