Pasos proyecto

1.- Crear proyecto Maven (maven-archetype-quickstart)
2.- Añadir dependencias: Mysql e hibernate

<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.32</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>5.6.15.Final</version>
		</dependency>

3.- Creo la clase HibernateUtil

package com.trifulcas.hibernate;

import java.util.Properties;

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtil {
	  private static  SessionFactory sessionFactory;
	 
	    public static SessionFactory getSessionFactory() {
	    	if (sessionFactory == null) {
				try {
					Configuration configuration = new Configuration();

					// Hibernate settings equivalent to hibernate.cfg.xml's properties
					Properties settings = new Properties();
					settings.put(Environment.DRIVER, "com.mysql.cj.jdbc.Driver");
					settings.put(Environment.URL, "jdbc:mysql://localhost:3306/sakila");
					settings.put(Environment.USER, "root");
					settings.put(Environment.PASS, "");
					settings.put(Environment.DIALECT, "org.hibernate.dialect.MySQL5Dialect");

					settings.put(Environment.SHOW_SQL, "true");

					settings.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, "thread");


					configuration.setProperties(settings);
					
					

					ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
							.applySettings(configuration.getProperties()).build();
					
					sessionFactory = configuration.buildSessionFactory(serviceRegistry);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			return sessionFactory;
	    }
	 
	    public static void shutdown() {
	        // Close caches and connection pools
	        getSessionFactory().close();
	    }
}

4.- Pongo los datos correctos de conexión: BD, usuario y password (settings.put(Environment.URL, “jdbc:mysql://localhost:3306/biblioteca”);)
5.- Creo mi entidad

package com.trifulcas.models;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "genero")
public class Genero {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "idgenero")
	private int idGenero;

	private String nombre;

	public Genero() {
		super();
		// TODO Auto-generated constructor stub
	}

	public int getIdGenero() {
		return idGenero;
	}

	public void setIdGenero(int idGenero) {
		this.idGenero = idGenero;
	}

	public String getNombre() {
		return nombre;
	}

	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	@Override
	public String toString() {
		return "Genero [idGenero=" + idGenero + ", nombre=" + nombre + "]";
	}

	
}

6.- Lo anotamos en hibernateutil

...
				configuration.addAnnotatedClass(Genero.class);
...

7.- Lo pruebo:

Session session = HibernateUtil.getSessionFactory().openSession();
		try {
			Genero g = session.get(Genero.class, 1);
			System.out.println(g);
		} catch (Exception ex) {
			System.out.println(ex);
		}
		session.close();

Onetomany

package com.trifulcas.models;

import java.util.Date;
import java.util.List;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.persistence.Temporal;
import jakarta.persistence.TemporalType;

@Entity
@Table(name = "city")
public class City {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "city_id")
	private Short cityId;

	@Column(name = "city", nullable = false)
	private String city;

	// En la entidad de 'varios' ponemos ManyToOne
	@ManyToOne
	// Especificamos cual es la clave foránea de esta relación
	@JoinColumn(name = "country_id", nullable = false)
	// La propiedad siempre será la entidad relacionada
	private Country country; // Cuando recuperamos la entidad se cargan automáticamente las entidades relacionadas
	// Es decir, cuando yo cargo una ciudad se carga su país
	// Y puedo acceder a sus valores

	@OneToMany(mappedBy="city",cascade=CascadeType.ALL)
	private List<Address> addreses;
	
	@Column(name = "last_update", nullable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
	@Temporal(TemporalType.TIMESTAMP)
	private java.util.Date lastUpdate = new Date();

	// Constructor, getters, and setters

	public City() {
	}

	public City(String city, Country country) {
		this.city = city;
		this.country = country;
	}

	public Short getCityId() {
		return cityId;
	}

	public void setCityId(Short cityId) {
		this.cityId = cityId;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	public Country getCountry() {
		return country;
	}

	public void setCountry(Country country) {
		this.country = country;
	}

	public java.util.Date getLastUpdate() {
		return lastUpdate;
	}

	public void setLastUpdate(java.util.Date lastUpdate) {
		this.lastUpdate = lastUpdate;
	}

	public List<Address> getAddreses() {
		return addreses;
	}

	public void setAddreses(List<Address> addreses) {
		this.addreses = addreses;
	}

	// Cuidado con poner country porque entramos en bucle
	@Override
	public String toString() {
		return "City [cityId=" + cityId + ", city=" + city + ", country="+country.getCountry()+"]";
	}

}

package com.trifulcas.models;

import java.sql.Timestamp;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;

@Entity
@Table(name = "address")
public class Address {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "address_id")
    private short addressId;

    @Column(name = "address", nullable = false, length = 50)
    private String address;

    @Column(name = "address2", length = 50)
    private String address2;

    @Column(name = "district", nullable = false, length = 20)
    private String district;

    @ManyToOne
    @JoinColumn(name="city_id")
    private City city;
   
   

	@Column(name = "postal_code", length = 10)
    private String postalCode;

    @Column(name = "phone", nullable = false, length = 20)
    private String phone;

    @Column(name = "last_update", nullable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
    private Timestamp lastUpdate;

    // Getters and Setters

    public short getAddressId() {
        return addressId;
    }

    public void setAddressId(short addressId) {
        this.addressId = addressId;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getAddress2() {
        return address2;
    }

    public void setAddress2(String address2) {
        this.address2 = address2;
    }

    public String getDistrict() {
        return district;
    }

    public void setDistrict(String district) {
        this.district = district;
    }
    public City getCity() {
		return city;
	}

	public void setCity(City city) {
		this.city = city;
	}

    public String getPostalCode() {
        return postalCode;
    }

    public void setPostalCode(String postalCode) {
        this.postalCode = postalCode;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public Timestamp getLastUpdate() {
        return lastUpdate;
    }

    public void setLastUpdate(Timestamp lastUpdate) {
        this.lastUpdate = lastUpdate;
    }

	@Override
	public String toString() {
		return "Address [addressId=" + addressId + ", address=" + address + ", address2=" + address2 + ", district="
				+ district + ", city=" + city + ", postalCode=" + postalCode + ", phone=" + phone + ", lastUpdate="
				+ lastUpdate + "]";
	}
    
}

No olvideis anotar en HibernateUtil:

...
		configuration.addAnnotatedClass(Address.class);
...

Resultset

package com.trifulcas.country;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;

public class GetCountries {

	public static void main(String[] args) {
		// Buscar todos los países que tengan un texto determinado
		Scanner scanner = new Scanner(System.in);
		// Pido el texto
		System.out.println("Introduzca el texto a buscar");
		String texto = scanner.nextLine();
		try {
			// Hago lo estándar
			Class.forName("com.mysql.cj.jdbc.Driver");
			Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/sakila", "root", "");
			Statement st = con.createStatement();
			// ¿QUé sql necesito?
			String sql = "select * from country where country like '%"+texto+"%'";
			System.out.println(sql);
			// Aquí no modificamos sino que seleccionamos, por lo tanto usamos
			// executeQuery para ejecutar y un ResultSet para almacenar los resultados
			ResultSet rs=st.executeQuery(sql);
			// rs es un cursor, puntero o flecha, como lo queramos llamar
			// a los registros de la base de datos
			rs.next(); // Esto me coloca el cursor en el primer elemento
			System.out.println(rs.getString(2)); // Esto me imprime el nombre del primer país
			rs.next(); // Esto me coloca el cursor en el primer elemento
			System.out.println(rs.getString("country")); // Esto me imprime el nombre del segundo país
			// Si yo hago un bucle recorro todos los registros
			while(rs.next()) {
				System.out.println(rs.getString("country")); 			
			}	
			st.close();
			con.close();
		} catch (Exception ex) {
			System.out.println(ex.getMessage());
		}
		scanner.close();
	}

}
package com.trifulcas.country;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;

public class GetCountries {

	public static void main(String[] args) {
		// Buscar todos los países que tengan un texto determinado
		Scanner scanner = new Scanner(System.in);
		// Pido el texto
		System.out.println("Introduzca el texto a buscar");
		String texto = scanner.nextLine();
		try {
			// Hago lo estándar
			Class.forName("com.mysql.cj.jdbc.Driver");
			Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/sakila", "root", "");
			Statement st = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
			// ¿Qué sql necesito?
			String sql = "select * from country where country like '%"+texto+"%'";
			System.out.println(sql);
			// Aquí no modificamos sino que seleccionamos, por lo tanto usamos
			// executeQuery para ejecutar y un ResultSet para almacenar los resultados
			ResultSet rs=st.executeQuery(sql);
			// rs es un cursor, puntero o flecha, como lo queramos llamar
			// a los registros de la base de datos
			rs.next(); // Esto me coloca el cursor en el primer elemento
			System.out.println(rs.getString(2)); // Esto me imprime el nombre del primer país
			rs.next(); // Esto me coloca el cursor en el primer elemento
			System.out.println(rs.getString("country")); // Esto me imprime el nombre del segundo país
			// Si yo hago un bucle recorro todos los registros
			while(rs.next()) {
				System.out.println(rs.getString("country")); 			
			}	
			// Al tener el tipo TYPE_SCROLL_INSENSITIVE puedo ir a registros determinados
			rs.first();
			System.out.println(rs.getString("country")); // Esto me imprime el nombre del primer país
			rs.last();
			System.out.println(rs.getString("country")); // Esto me imprime el nombre del último país
			
			rs.absolute(4);
			System.out.println(rs.getString("country")); // Esto me imprime el nombre del último país
			
			st.close();
			con.close();
		} catch (Exception ex) {
			System.out.println(ex.getMessage());
		}
		scanner.close();
	}

}

Lo habitual es hacerlo así:

ResultSet rs=st.executeQuery(sql);
			// Si yo hago un bucle recorro todos los registros
			while(rs.next()) {
				System.out.println(rs.getString("country")); 			
			}	

Soluciones ejercicios

package com.trifulcas.country;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.Scanner;

public class AddCategory {

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		System.out.println("Introduzca el nombre de la categoría");
		String categoria = scanner.nextLine();
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/sakila", "root", "");
			Statement st = con.createStatement();
			String sql = "insert into category (name) values ('" + categoria + "')";
			System.out.println(sql);
			int res = st.executeUpdate(sql);
			System.out.println(res + " registros afectados");
			st.close();
			con.close();
		} catch (Exception ex) {
			System.out.println(ex.getMessage());
		}
	}

}

package com.trifulcas.country;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class UpdatePayments {

	public static void main(String[] args) {
			try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/sakila", "root", "");
			Statement st = con.createStatement();
			
			String sql = "update payment set amount=amount+0.5";
			System.out.println(sql);
			int res = st.executeUpdate(sql);
			System.out.println(res + " registros afectados");
			st.close();
			con.close();
		} catch (Exception ex) {
			System.out.println(ex.getMessage());
		}
	}

}

package com.trifulcas.country;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.Scanner;

public class AddActors {

	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		System.out.println("Introduzca el número de actores");
		int cantidad = scanner.nextInt();
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/sakila", "root", "");
			Statement st = con.createStatement();
			for (int i = 1; i <= cantidad; i++) {
				String sql = "insert into actor (first_name,last_name) values ('actor"+i+"','actor"+i+"');";
				System.out.println(sql);
				int res = st.executeUpdate(sql);
				System.out.println(res + " registros afectados");
			}
			st.close();
			con.close();
		} catch (Exception ex) {
			System.out.println(ex.getMessage());
		}
	}

}

Conexión base de datos

Para conectarnos desde java a las bases de datos tenemos varias opciones. Empezaremos con la más sencilla y en días sucesivos veremos otras más complejas.

En un proyecto Java podemos añadir el conector mysql. Primero lo tenemos que descargar, si queréis lo podéis hacer desde aquí:

https://github.com/juanpablofuentes/JavaNetmind/tree/main/MiPrimerProyecto/src

https://dev.mysql.com/downloads/connector/j/

Botón derecho guardar archivo mysql connector

Creamos un nuevo proyecto (para no mezclar) y añadimos este jar a las librerías de nuestro proyecto. Un manual:

https://www.knowprogram.com/jdbc/connect-mysql-database-eclipse/

Una vez lo tengamos añadido podemos conectarnos a nuestra base de datos con la cadena de conexión, de manera parecida a como lo hacemos en el workbench, indicando la url del servidor, la base de datos, y el usuario y la contraseña:

	Class.forName("com.mysql.cj.jdbc.Driver");
			Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/sakila", "root", "");

A partir de aquí podemos acceder a la base de datos:


Statement stmt = con.createStatement();
			ResultSet rs = stmt.executeQuery("select * from actor");
			while (rs.next()) {
				System.out.println(rs.getInt(1) + "  " + rs.getString(2) + "  " + rs.getString(3));
			}
			rs = stmt.executeQuery("select * from actor");
			while (rs.next()) {
				System.out.println(
						rs.getInt("actor_id") + "  " + rs.getString("first_name") + "  " + rs.getString("last_name"));
			}

			int result=stmt.executeUpdate("insert into actor (first_name, last_name) values ('Eva','Pi')");  
			System.out.println(result+" filas afectadas");

			PreparedStatement ps = con.prepareStatement("select * from actor where first_name like ?");
			ps.setString(1, "%ar%");
			rs = ps.executeQuery();
			while (rs.next()) {
				System.out.println(
						rs.getInt("actor_id") + "  " + rs.getString("first_name") + "  " + rs.getString("last_name"));
			}

Repaso OOP 7: Interfaces

package com.trifulcas.repaso.oop;

// Un interface se declara con la palabra clave Interface
// En principio se definen métodos sin implementación
// Cada clase que implemente este interfaz se compromete
// a implementar los métodos definidos en el interface
public interface Saludador {
	public void hola();
	public void adios();
}

package com.trifulcas.repaso.oop;

// Para implementar un interface uso implements
public class AlumnoIntercambio extends Alumno implements Saludador {

	private String paisOrigen;
	
	public String getPaisOrigen() {
		return paisOrigen;
	}

	public void setPaisOrigen(String paisOrigen) {
		this.paisOrigen = paisOrigen;
	}

	public AlumnoIntercambio(String nombre, int nota, String email) {
		super(nombre, nota, email);
		
	}
	public void saludo() {
		// Recordad que las propiedades private no son visibles desde
		// la clase derivada, esto da error
		// System.out.println("hola "+nombre);
		System.out.println("hola "+getNombre());
	}
	// Sobreescribir los métodos que heredo de la clase madre
	// Y tener otra implementación, en este caso el toString
	@Override
	public String toString() {
		// La palabra clave super hace referencia a la clase madre
		// Aquí lo usamos para acceder al método toString de Alumno
		return "AlumnoIntercambio [paisOrigen=" + paisOrigen + ", " + super.toString() + "]";
	}

	// Si clase madre tiene un método abstracto en la clase derivada
	// Estamos obligados a  implementarlo
	@Override
	public int media() {
		return 0;
	}
	
	// Como implemento el interfaz Saludados tengo que
	// implementar hola y adios
	@Override
	public void hola() {
		System.out.println("hola");
	}

	@Override
	public void adios() {
		System.out.println("adios");
		
	}
	

}

package com.trifulcas.repaso.oop;

public class Rectangulo extends Figura implements Saludador, Imprimible{
	private double base;
	private double altura;
	public Rectangulo(double base, double altura) {
		super();
		this.base = base;
		this.altura = altura;
	}
	public double getBase() {
		return base;
	}
	public void setBase(double base) {
		this.base = base;
	}
	public double getAltura() {
		return altura;
	}
	public void setAltura(double altura) {
		this.altura = altura;
	}
	@Override
	public double getArea() {
		// TODO Auto-generated method stub
		return base*altura;
	}
	@Override
	public double getPerimetro() {
		// TODO Auto-generated method stub
		return base+2+altura*2;
	}
	
	// Como implemento el interfaz Saludados tengo que
	// implementar hola y adios
	@Override
	public void hola() {
		System.out.println("hola, soy un rectángulo");
		
	}
	@Override
	public void adios() {
		System.out.println("Adios pásalo bien");
		
	}
	@Override
	public void imprimir() {
		System.out.println("Imprimir rectángulo");
	}
	
}

package com.trifulcas.repaso.oop;

import java.util.ArrayList;

public class TestOOP {

	public static void main(String[] args) {

		// Puedo crear arraylist de interfaces
		ArrayList<Saludador> saludadores = new ArrayList<>();
		saludadores.add(new Rectangulo(2, 3));
		saludadores.add(new AlumnoIntercambio("Ana", 3, "www"));
		saludadores.add(new Rectangulo(8, 5));
		// Polimorfismo: como todas las clases implementan Saludador
		// Yo utilizo los métodos que sé que tendrán que implementar
		// porque el interfaz es como un contrato
		for (Saludador saludador : saludadores) {
			saludador.hola();
			saludador.adios();
			// Esto no es visible saludador.getArea()
			// Esto tampoco es visible saludador.getPaisOrigen()
		}
		
		Tigre pepe=new Tigre();
		pepe.amamantar();
		
	}

}

Repaso OOP 6: Abstracción

package com.trifulcas.repaso.oop;

// Una clase abstracta es igual que una clase con la diferencia
// de que no se puede instanciar un objeto de ella
public abstract class Alumno {

	// Lo habitual es que todas las propiedades sean private
	// Para evitar que se puedan modificar desde el exterior
	private String nombre;

	private int nota;

	private String mail;
	
	// En una clase abstracta puedo tener métodos abstractos
	// Son métodos con 'firma' (parámetros y tipo de retorno)
	// Pero sin implementación
	// Un método abastracto solo puede estar en una clase abstracta
	
	public abstract int media();
	
	// Las propiedades o métodos estáticos solo existen una vez
	// (es decir, hay una única instancia para todos los objetos de esta clase)
	// Podemos acceder a ellos sin instanciar un objeto
	// La información es compartida por todos
	private static int notaCorte=5;

	// El constructor es la manera como se construye la instancia
	// de la clase. Es el punto de entrada
	// Podemos tener parámetros o no y podemos tener sobrecargas

	// Un ejemplo típico sería este. Usamos todas las propiedades

	public Alumno(String nombre, int nota, String email) {
		// La palabra clave this hace referencia al propio objeto
		// La usamos para desambiguar entre el nombre de los parámetros
		// y de las propiedades de la clase
		this.nombre = nombre;
		this.nota = nota;
		// Aquí no hace falta desambiguar porque se llaman diferente
		mail = email;
	}

	// Yo los constructores los puedo sobrecargar
	public Alumno(String nombre, int nota) {
		this.nombre = nombre;
		this.nota = nota;
		mail = "No tiene";
		
		// this(nombre,nota,"No tiene")
	}
	
	// Si yo hago sobrecarga lo suyo es que llamemos al otro constructor
	public Alumno(String nombre) {
		/* Si yo quiero hacer esto
		this.nombre = nombre;
		this.nota = 0;
		mail = "No tiene";
		Lo mejor es hacer esto:
		*/
		this(nombre,0,"No tiene"); // this hace referencia al constructor
	}

	public String getNombre() {
		return nombre;
	}

	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	public int getNota() {
		return nota;
	}

	public void setNota(int nota) {
		this.nota = nota;
	}

	public String getMail() {
		return mail;
	}

	public void setMail(String mail) {
		this.mail = mail;
	}
	public boolean getAprobado() {
		// La nota de corte es la misma para todos los objetos
		return nota>=notaCorte;
	}
	
	
	public static int getNotaCorte() {
		return notaCorte;
	}

	public static void setNotaCorte(int notaCorte) {
		Alumno.notaCorte = notaCorte;
	}

	@Override
	public String toString() {
		return "Alumno [nombre=" + nombre + ", nota=" + nota + ", mail=" + mail + "]";
	}

	public static void aprobar(Alumno al) {
		al.setNota(10);
	}
}

package com.trifulcas.repaso.oop;

// La herencia se implementa con extends
// AlumnoIntercambio deriva de Alumno
// Alumno es la superclase o clase madre 
// y AlumnoIntercambio la clase hija o derivada o subclase
public class AlumnoIntercambio extends Alumno {

	private String paisOrigen;
	
	public String getPaisOrigen() {
		return paisOrigen;
	}

	public void setPaisOrigen(String paisOrigen) {
		this.paisOrigen = paisOrigen;
	}

	public AlumnoIntercambio(String nombre, int nota, String email) {
		super(nombre, nota, email);
		
	}
	public void saludo() {
		// Recordad que las propiedades private no son visibles desde
		// la clase derivada, esto da error
		// System.out.println("hola "+nombre);
		System.out.println("hola "+getNombre());
	}
	// Sobreescribir los métodos que heredo de la clase madre
	// Y tener otra implementación, en este caso el toString
	@Override
	public String toString() {
		// La palabra clave super hace referencia a la clase madre
		// Aquí lo usamos para acceder al método toString de Alumno
		return "AlumnoIntercambio [paisOrigen=" + paisOrigen + ", " + super.toString() + "]";
	}

	// Si clase madre tiene un método abstracto en la clase derivada
	// Estamos obligados a  implementarlo
	@Override
	public int media() {
		return 0;
	}
	// En una clase que no es abstracta no puedo tener un método abstracto
	// Error: public abstract int foo();
	

}

package com.trifulcas.repaso.oop;

public abstract class Figura {
	public abstract double getArea();
	public abstract double getPerimetro();
}

package com.trifulcas.repaso.oop;

public class Cuadrado extends Figura{
	private double lado;

	public Cuadrado(int lado) {
		super();
		this.lado = lado;
	}

	public double getLado() {
		return lado;
	}

	public void setLado(double lado) {
		this.lado = lado;
	}

	@Override
	public double getArea() {
		// TODO Auto-generated method stub
		return lado*lado;
	}

	@Override
	public double getPerimetro() {
		// TODO Auto-generated method stub
		return lado*4;
	}
	
}

package com.trifulcas.repaso.oop;

public class Rectangulo extends Figura{
	private double base;
	private double altura;
	public Rectangulo(double base, double altura) {
		super();
		this.base = base;
		this.altura = altura;
	}
	public double getBase() {
		return base;
	}
	public void setBase(double base) {
		this.base = base;
	}
	public double getAltura() {
		return altura;
	}
	public void setAltura(double altura) {
		this.altura = altura;
	}
	@Override
	public double getArea() {
		// TODO Auto-generated method stub
		return base*altura;
	}
	@Override
	public double getPerimetro() {
		// TODO Auto-generated method stub
		return base+2+altura*2;
	}
	
}

package com.trifulcas.repaso.oop;

import java.util.ArrayList;

public class TestOOP {

	public static void main(String[] args) {
		

		// Esto ahora da error porque al ser abstracta Alumno
		// No podemos crear una instancia
		// Alumno eva=new Alumno("Eva",6,"wwww");
		// No puedo hacer Figura foo=new Figura()
		ArrayList<Figura> figuras=new ArrayList<>();
		figuras.add(new Cuadrado(5));
		figuras.add(new Rectangulo(2,3));
		figuras.add(new Cuadrado(7));
		figuras.add(new Rectangulo(12,4));
		// Polimorfismo: como todas las clases derivan de figura
		// Yo utilizo los métodos que sé que tendrán por derivar
		// de 'Figura', aunque cada clase tiene su propia implementación
		for(Figura figura:figuras) {
			System.out.println(figura.getArea());
		}
	}

}

Repaso OOP 5: Herencia

package com.trifulcas.repaso.oop;

// La herencia se implementa con extends
// AlumnoIntercambio deriva de Alumno
// Alumno es la superclase o clase madre 
// y AlumnoIntercambio la clase hija o derivada o subclase
public class AlumnoIntercambio extends Alumno {

	private String paisOrigen;
	
	public String getPaisOrigen() {
		return paisOrigen;
	}

	public void setPaisOrigen(String paisOrigen) {
		this.paisOrigen = paisOrigen;
	}

	public AlumnoIntercambio(String nombre, int nota, String email) {
		super(nombre, nota, email);
		
	}
	public void saludo() {
		// Recordad que las propiedades private no son visibles desde
		// la clase derivada, esto da error
		// System.out.println("hola "+nombre);
		System.out.println("hola "+getNombre());
	}
	// Sobreescribir los métodos que heredo de la clase madre
	// Y tener otra implementación, en este caso el toString
	@Override
	public String toString() {
		// La palabra clave super hace referencia a la clase madre
		// Aquí lo usamos para acceder al método toString de Alumno
		return "AlumnoIntercambio [paisOrigen=" + paisOrigen + ", " + super.toString() + "]";
	}

	

}

package com.trifulcas.repaso.oop;

public class TestOOP {

	public static void main(String[] args) {
		
		AlumnoIntercambio john=new AlumnoIntercambio("John",6,"eee");
		// Al derivar de alumno John tiene todas las propiedades
		// Y métodos que tiene alumno
		System.out.println(john.getAprobado());
		john.setMail("pepe@pee.com");
		System.out.println(john);
		// La subclase puede tener sus propios métodos y propiedades
		john.setPaisOrigen("Bélgica");
		System.out.println(john);
		Alumno eva=new Alumno("Eva",6,"wwww");
		// La superclase no tiene las propiedades de las subclases
		// Esto da error eva.getPaisOrigen()
		
		// Yo puedo definir una variable como la clase madre
		// Pero instanciarla como la clase hija
		// Para qué? Polimorfismo
		Alumno pep=new AlumnoIntercambio("pep",4,"ww");
	}

}

Repaso OOP 4: static

package com.trifulcas.repaso.oop;

// Las clases las definimos con la palabra clave class
// Y el nombre de la clase primera en mayúsculas
// Recordad que en java el nombre del archivo y la clase debe ser el mismo

public class Alumno {

	// Lo habitual es que todas las propiedades sean private
	// Para evitar que se puedan modificar desde el exterior
	private String nombre;

	private int nota;

	private String mail;
	
	// Las propiedades o métodos estáticos solo existen una vez
	// (es decir, hay una única instancia para todos los objetos de esta clase)
	// Podemos acceder a ellos sin instanciar un objeto
	// La información es compartida por todos
	private static int notaCorte=5;

	// El constructor es la manera como se construye la instancia
	// de la clase. Es el punto de entrada
	// Podemos tener parámetros o no y podemos tener sobrecargas

	// Un ejemplo típico sería este. Usamos todas las propiedades

	public Alumno(String nombre, int nota, String email) {
		// La palabra clave this hace referencia al propio objeto
		// La usamos para desambiguar entre el nombre de los parámetros
		// y de las propiedades de la clase
		this.nombre = nombre;
		this.nota = nota;
		// Aquí no hace falta desambiguar porque se llaman diferente
		mail = email;
	}

	// Yo los constructores los puedo sobrecargar
	public Alumno(String nombre, int nota) {
		this.nombre = nombre;
		this.nota = nota;
		mail = "No tiene";
		
		// this(nombre,nota,"No tiene")
	}
	
	// Si yo hago sobrecarga lo suyo es que llamemos al otro constructor
	public Alumno(String nombre) {
		/* Si yo quiero hacer esto
		this.nombre = nombre;
		this.nota = 0;
		mail = "No tiene";
		Lo mejor es hacer esto:
		*/
		this(nombre,0,"No tiene"); // this hace referencia al constructor
	}

	public String getNombre() {
		return nombre;
	}

	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	public int getNota() {
		return nota;
	}

	public void setNota(int nota) {
		this.nota = nota;
	}

	public String getMail() {
		return mail;
	}

	public void setMail(String mail) {
		this.mail = mail;
	}
	public boolean getAprobado() {
		// La nota de corte es la misma para todos los objetos
		return nota>=notaCorte;
	}
	
	
	public static int getNotaCorte() {
		return notaCorte;
	}

	public static void setNotaCorte(int notaCorte) {
		Alumno.notaCorte = notaCorte;
	}

	@Override
	public String toString() {
		return "Alumno [nombre=" + nombre + ", nota=" + nota + ", mail=" + mail + "]";
	}

	
}

package com.trifulcas.repaso.oop;

public class Utils {
	// Si mi clase tiene métodos estáticos
	public static boolean esPrimo(int numero) {
		for (int i = 2; i < numero; i++) {
			if (numero % i == 0) {
				return false;
			}
		}
		return true;
	}

	public static boolean esPar(int numero) {
		return numero % 2 == 0;
	}
}

package com.trifulcas.repaso.oop;

import java.util.Arrays;

public class TestOOP {

	public static void main(String[] args) {
		
		Alumno ana=new Alumno("Ana",7,"ana@ana.com");
		System.out.println(ana.getNotaCorte());
		// Si yo cambio el valor de la nota de corte
		ana.setNotaCorte(7);
		Alumno eva = new Alumno("Eva",6);
		// La cambio para todos los objetos
		System.out.println(eva.getNotaCorte());
		
		// Puedo acceder sin instanciar el objeto
		Alumno.setNotaCorte(8);
		System.out.println(eva.getNotaCorte());
		System.out.println(ana.getNotaCorte());
		
		Alumno[] clase=new Alumno[10];
		// Creando 10 alumnos
		for(int i=0;i<10;i++) {
			clase[i]=new Alumno("Alumno"+i,i);
		}
		System.out.println(Arrays.toString(clase));
		
		// Yo puedo usar los métodos estáticos de una clase sin necesidad
		// de instanciar un objeto de esa clase
		System.out.println(Utils.esPar(10));
		System.out.println(Utils.esPrimo(17));
		// Esto no es necesario
		Utils foo=new Utils();
		System.out.println(foo.esPar(8));
	}

}

Repaso OOP 3: Constructores

package com.trifulcas.repaso.oop;

// Las clases las definimos con la palabra clave class
// Y el nombre de la clase primera en mayúsculas
// Recordad que en java el nombre del archivo y la clase debe ser el mismo

public class Alumno {

	// Lo habitual es que todas las propiedades sean private
	// Para evitar que se puedan modificar desde el exterior
	private String nombre;

	private int nota;

	private String mail;

	// El constructor es la manera como se construye la instancia
	// de la clase. Es el punto de entrada
	// Podemos tener parámetros o no y podemos tener sobrecargas

	// Un ejemplo típico sería este. Usamos todas las propiedades

	public Alumno(String nombre, int nota, String email) {
		// La palabra clave this hace referencia al propio objeto
		// La usamos para desambiguar entre el nombre de los parámetros
		// y de las propiedades de la clase
		this.nombre = nombre;
		this.nota = nota;
		// Aquí no hace falta desambiguar porque se llaman diferente
		mail = email;
	}

	// Yo los constructores los puedo sobrecargar
	public Alumno(String nombre, int nota) {
		this.nombre = nombre;
		this.nota = nota;
		mail = "No tiene";
		
		// this(nombre,nota,"No tiene")
	}
	
	// Si yo hago sobrecarga lo suyo es que llamemos al otro constructor
	public Alumno(String nombre) {
		/* Si yo quiero hacer esto
		this.nombre = nombre;
		this.nota = 0;
		mail = "No tiene";
		Lo mejor es hacer esto:
		*/
		this(nombre,0,"No tiene"); // this hace referencia al constructor
	}

	public String getNombre() {
		return nombre;
	}

	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	public int getNota() {
		return nota;
	}

	public void setNota(int nota) {
		this.nota = nota;
	}

	public String getMail() {
		return mail;
	}

	public void setMail(String mail) {
		this.mail = mail;
	}

}

package com.trifulcas.repaso.oop;

public class TestOOP {

	public static void main(String[] args) {
		
		// Como el constructor de Alumno tiene parámetros
		// Ahora tenemos que pasar los valores que nos piden
		// Cada vez que hagamos una instancia del objeto
		Alumno ana=new Alumno("Ana",7,"ana@ana.com");
		
		// Como tengo sobrecargado el constructor puedo llamarlo
		// solo con dos parámetros
		Alumno eva = new Alumno("Eva",6);
		
		
	}

}