Como ya se vio en la entrada de las clases y objetos, se definió clase como el conjunto de códigos utilizado para poder instanciar objetos. Sin embargo no siempre es así, ya que si una clase es abstracta no se puede utilizar para instanciar objetos, sino que servirá de base para el resto de clases que hereden de ella. La sintaxis de una clase abstracta es:

public abstract class Empleado {}

La palabra abstract indica que la clase no podrá ser utilizada para instanciar objetos. Dentro de la clase si se podrán escribir tanto variables como métodos, los cuales serán heredados por subclases pero al menos uno de ellos no puede tener cuerpo definido.

public abstract class Empleado {

    int antiguedad;
    int salario;
    String nombre;
    String apellido;
    
    void calcularSalario();
    void mostrarDatos(){
        System.out.println("El empleado tiene como salario base: "+this.salario);
    } 
}

En este caso no podrá existir un objeto de tipo empleado, a no ser que se escriban todos aquellos métodos que han sido declarados como abstractos en la clase

public class Ejecucion {
    
    public static void main(String[]args){
        Empleado empleado = new Empleado() {
            @Override
            void calcularSalario() {
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
            }
        };
    }
}

Sin embargo el principal uso de una clase abstracta es servir de base para otras clases que heredarán los métodos y variables, estando obligadas estas clases a escribir los métodos abstractos

public class TrabajadorIT extends Empleado{

    public TrabajadorIT(int salario) {
        this.salario = salario;
    }

    @Override
    void calcularSalario() {
        double salarioMensual = (this.salario * 0.25) + this.salario;
        System.out.println("El salario mensual como trabajador de IT es: "+salarioMensual);
    }
}

En este ejemplo la clase TrabajadorIT hereda de la clase Empleado (por la palabra extends) obligando a escribir el método abtracto calcularSalario(). Dentro de este método se utiliza la variable antigüedad y salario de la clase Empleado (gracias a la herencia) para calcular el salario mensual. En este caso la clase TrabajadorIT si puede ser utilizada para crear objetos ya que no existe ningún método abstracto

public class Ejecucion {
    
    public static void main(String[]args){
        /*Empleado empleado = new Empleado() {
            @Override
            void calcularSalario() {
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
            }
        };*/
        TrabajadorIT informatico = new TrabajadorIT(1800);
        informatico.mostrarDatos();
        informatico.calcularSalario();   
    }
}

siendo la salida

El empleado tiene como salario base: 1800
El salario mensual como trabajador de IT es: 2250.0

Los códigos se pueden descargar desde el repositorio