CamelCase: pràctica d’escriure frases o paraules compostes eliminant espais i posant en majúscula la primera lletra de cada paraula.
Pot ser UpperCamelCase o lowerCamelCase.
Es recomanable evitar caràcters que no siguin lletres o números.
A Java, les expressions s'avaluen d'esquerra a dreta.
Java no executarà parts de l'expressió quan no sigui necessari. En particular:
false
, ja no es continua avaluant a la dreta.true
, ja no es continua avaluant a la dreta.Quan diversos tipus intervenen en una expressió, tots es converteixen al mateix tipus mitjançant unes normes de promoció. Per començar, tots els char / byte / short es promouen a int. Si hi ha algun long, a long. Si hi ha algun float, a float. I si hi ha algun double, a double.
La conversió només es pot fer amb tipus numèrics (exclou el boolean). Hi ha de dos tipus:
També tenim el boxing / unboxing, que permet convertir automàticament entre els tipus primitius i les classes embolcall.
Tenim dos tipus:
L'operació de downcasting sol venir precedida de l'ús de l'operador instanceof
. Aquest operador retorna true si la classe és del tipus que es pregunta, si és una subclasse o si implementa la interfície.
Java passa els paràmetres d'un mètode per valor. Però el valor d'un objecte és una referència. Això també inclou qualsevol array (de primitius o objectes).
Per tant, mai podem modificar el valor d'una variable primitiva, ni el d'un objecte (la referència). El que es pot fer és, si l'objecte és mutable, modificar-lo.
RuntimeException
, and are usually implemented using IllegalArgumentException
, NullPointerException
, or IllegalStateException
Exception
Hem vist que podem tenir excepcions Checked (subclasses de Exception
) i Unchecked (subclasses de RuntimeException
).
Si mirem la jerarquia de classes, totes extenen Throwable
, la classe pare de totes:
java.lang.Throwable
java.lang.Error
java.lang.Exception
java.lang.RuntimeException
Els tres mètodes més importants de Throwable
són:
public String getMessage()
: conté el missatge d'excepció.public StackTraceElement[] getStackTrace()
: conté la traça de la pila de l'excepció.public Throwable getCause()
: opcionalment, conté una referència a l'excepció que ha causat aquesta. Pot ser una cadena de diverses excepcions.Un stacktrace no ha de ser necessàriament un error. Es pot obtenir el valor actual mitjançant aquest codi:
public class TestStackTrace {
public static void one() {
two();
}
public static void two() {
three();
}
public static void three() {
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
for (StackTraceElement elem : trace) {
System.out.println(elem);
}
}
public static void main(String[] args) {
one();
}
}
Si pots, guarda la causa quan facis throw d'una excepció més específica.
try {
doSomething();
} catch (NumberFormatException e) {
throw new MyBusinessException(e, ErrorCode.CONFIGURATION_ERROR);
} catch (IllegalArgumentException e) {
throw new MyBusinessException(e, ErrorCode.UNEXPECTED);
}
paquet.NomDeLaException: missatge que explica la excepció al getMessage()
at paquet.Classe.metode(Classe.java:XXX)
at paquet.Classe.metode(Classe.java:XXX)
...
Caused by: paquet.NomDeLaException: missatge que explica la excepció al getMessage()
at paquet.Classe.metode(Classe.java:XXX)
at paquet.Classe.metode(Classe.java:XXX)
...
A continuació veiem una excepció amb les causes encadenades (Caused by). Els punts suspensius expressen la repetició de les línies respecte de l'excepció pare.
org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:275)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
at org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.injectServices(DefaultIdentifierGeneratorFactory.java:152)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.injectDependencies(AbstractServiceRegistryImpl.java:286)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:243)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:179)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:119)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:904)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:935)
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:56)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
at cotxes.CotxesDAO.getEMF(CotxesDAO.java:205)
at cotxes.CotxesDAO.access$400(CotxesDAO.java:15)
at cotxes.CotxesDAO$JPATransaction.result(CotxesDAO.java:223)
at cotxes.CotxesDAO.findMarques(CotxesDAO.java:81)
at cotxes.ProvaCotxes.processCommand(ProvaCotxes.java:69)
at cotxes.ProvaCotxes.prova(ProvaCotxes.java:49)
at cotxes.ProvaCotxes.main(ProvaCotxes.java:18)
Caused by: org.hibernate.exception.JDBCConnectionException: Error calling DriverManager#getConnection
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:115)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
at org.hibernate.engine.jdbc.connections.internal.BasicConnectionCreator.convertSqlException(BasicConnectionCreator.java:118)
at org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionCreator.makeConnection(DriverManagerConnectionCreator.java:37)
at org.hibernate.engine.jdbc.connections.internal.BasicConnectionCreator.createConnection(BasicConnectionCreator.java:58)
at org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections.addConnections(DriverManagerConnectionProviderImpl.java:363)
at org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections.<init>(DriverManagerConnectionProviderImpl.java:282)
at org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections.<init>(DriverManagerConnectionProviderImpl.java:260)
at org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections$Builder.build(DriverManagerConnectionProviderImpl.java:401)
at org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl.buildPool(DriverManagerConnectionProviderImpl.java:112)
at org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl.configure(DriverManagerConnectionProviderImpl.java:75)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:100)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:246)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.buildJdbcConnectionAccess(JdbcEnvironmentInitiator.java:145)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:66)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:94)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
... 20 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:990)
at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:342)
at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2197)
at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2230)
at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2025)
at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:778)
at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:386)
at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:330)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:208)
at org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionCreator.makeConnection(DriverManagerConnectionCreator.java:34)
... 35 more
Caused by: java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:345)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:211)
at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:301)
... 50 more
public static <E> void printArray( E[] inputArray ) {
// Display array elements
for(E element : inputArray) {
System.out.printf("%s ", element);
}
System.out.println();
}
Hi pot haver moments en què voldreu restringir els tipus de tipus que es permeten passar a un tipus de paràmetre. Per exemple, un mètode que opera sobre números només pot voler acceptar instàncies de Number o de les seves subclasses. Per a què serveixen els paràmetres del tipus de límit.
Per declarar un paràmetre de tipus delimitat, enumereu el nom del paràmetre del tipus, seguit de la paraula clau extends
, seguit tipus delimitant.
public static <T extends Comparable<T>> T maximum(T x, T y, T z) {
T max = x; // assume x is initially the largest
if(y.compareTo(max) > 0) {
max = y; // y is the largest so far
}
if(z.compareTo(max) > 0) {
max = z; // z is the largest now
}
return max; // returns the largest object
}
Una declaració de classe genèrica sembla una declaració de classe no genèrica, tret que el nom de classe sigui seguit per una secció de paràmetre tipus.
Com en els mètodes genèrics, la secció de paràmetres de tipus d'una classe genèrica pot tenir un o més paràmetres de tipus separats per comes. Aquestes classes es coneixen com a classes parametrizades o tipus parametrizats perquè accepten un o més paràmetres.
public class Box<T> {
private T t;
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
}
Java permet definir classes dins de classes. Això permet agrupar i encapsular, fent més llegible i gestionable el codi.
És una classe relacionada amb la classe exterior, però que no pot fer referència a les variables d'instància d'aquesta. De fet, és com una classe normal que s'ha imbricat dins d'una altra, per qüestions de conveniència.
class OuterClass {
...
static class StaticNestedClass {
...
}
}
Les classes imbricades (no estàtiques) estan associades amb una instància de la classe que les conté.
class OuterClass {
...
class InnerClass {
...
}
}
Si una declaració utilitza una variable o paràmetre amb el mateix nom que una altra a un àmbit que el conté, llavors la declaració encobreix aquesta, i podem accedir-hi amb la sintaxi OuterClass.this.variable
.
Una classe es pot definir localment, en qualsevol bloc de codi. Aquestes classes només poden accedir variables locals que siguin finals o efectivament finals: el seu valor no canvia després d'una declaració amb inicialització.
public class LocalClassExample {
...
public static void metode() {
...
class LocalClass {
...
}
}
}
Les classes anònimes permeten declarar i inicialitzar una classe al mateix temps. Són com classes locals, però sense nom. S'utilitzen quan només cal utilitzar una classe un cop. Es consideren expressions.
Es componen de:
...
Runnable tasca = new Runnable() {
@Override
public void run() {
...
}
};
...
Les classes anònimes no poden contenir declaracions de constructors, ni poden accedir a variables locals que no siguin finals o efectivament finals.
Les expressions lambda són molt habituals al disseny d'interfícies gràfiques.
Exemple de gestió d'un esdeveniment d'un botó (control de tipus Button
):
button.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Botó clicat!");
}
});
Aquest codi utilitza classes anònimes.
També podem utilitzar expressions Lambda, ja que els gestors d'esdeveniments són interfícies funcionals (un sol mètode abstracte):
buttn.setOnAction(
event -> System.out.println("Botó clicat!")
);
Veure https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
Properties props = new Properties();
props.load(inputStream);
String value = props.getProperty("nom.propietat"); // null, si no existeix
InputStream inputStream;
// possibles valors d'inputStream:
inputStream = new FileInputStream("/path/nom.properties");
inputStream = NomClasse.class.getResourceAsStream("/package1/package2/nom.properties");
inputStream = objecte.getClass().getResourceAsStream("/package1/package2/nom.properties");
Quan s'utilitza getResourceAsStream(), podem també utilitzar path relatiu a la classe (NomClasse o classe de l'objecte), però cal que l'arxiu es copiï a la carpeta del classpath (bin o com es digui).