Affinità con il C e il C++
Semplicità
Linguaggio orientato all'oggetto (Object-oriented)
Java soddisfa piuttosto bene a queste quattro esigenze. Infatti esistono le classi, le istanze delle quali costituiscono gli oggetti. Le variabili istanziate mantengono l'informazione di stato dei vari oggetti. Si può rendere riservata l'informazione attraverso la dichiarazione private, oppure la si può rendere astratta tramite la dichiarazione abstract (incapsulamento). Esiste comunicazione tra gli oggetti. I metodi posseduti da un oggetto stabiliscono il comportamento dell'oggetto stesso e manipolano le variabili istanziate della classe. In classi distinte possono esistere metodi diversi con lo stesso nome. Ogni oggetto risponde ai messaggi ricevuti secondo le caratteristiche che esso possiede (comportamento polimorfico). Da una classe possono essere create sottoclassi, le quali possiedono i metodi della classe da cui sono derivate (ereditarietà). Le classi derivate possono aggiungere nuovi metodi alla classe da cui derivano oppure possono sostituire ad essa alcuni metodi.
Gestione automatica della memoria
Neutralità all'architettura
Sorgente Java => compilatore Java => bytecodes => interprete Java => codice macchina specifico
I programmi Java quindi non hanno bisogno di alcun riadattamento quando vengono portati su sistemi differenti da quelli su cui sono stati sviluppati. I bytecodes rappresentano un codice macchina virtuale di elevata astrazione in modo che possano trovare una rappresentazione reale su ogni macchina. I programmi Java compilati in bytecodes possono viaggiare attraverso reti telematiche ed essere eseguiti sulle macchine provviste dell'interprete Java. Quest'ultimo è incluso nelle ultime versioni di Netscape Navigator (release 2.0 o superiore), il quale è quindi in grado di interpretare particolari programmi Java (applet) e visualizzare l'uscita di questi programmi nella propria finestra.
Linguaggio robusto
Dinamicità
Sicurezza
In questo compito di verifica, l'interprete fa uso dell'informazione aggiuntiva che il linguaggio macchina virtuale Java porta con sé. Per esempio, il caricamento nello stack di un intero e di un puntatore, che all'atto pratico sono la stessa cosa (sono entrambi numeri a 32 bit), è eseguita da due istruzioni macchina differenti (aload e iload). Inoltre, lo stato dello stack (ovvero i tipi di variabili che esso contiene) è conosciuto ancor prima che i programmi vengano eseguiti. Infatti non esistono istruzioni macchina che diano un risultato ambiguo, ovvero dato il tipo delle variabili di ingresso, è unicamente stabilito il tipo di variabile all'uscita. Per esempio, l'istruzione iadd addiziona due interi e produce sempre un intero. Ciò comporta che due percorsi di esecuzione uguali debbano generare alla fine della loro esecuzione lo stesso stato dello stack. Altri linguaggi di programmazione device-independent come il Postscript (usato dalle stampanti evolute) non hanno questa caratteristica. Se i bytecodes passano la verifica iniziale prima dell'esecuzione, si ha la certezza che non vengano compiute operazioni pericolose, come estrarre informazioni da una variabile privata per mezzo di qualche cast strano. Questo è importante, perché una variabile privata può contenere dati riservati, come il numero di carta di credito durante una transazione commerciale on-line.
Infine, come estremo mezzo per garantire la sicurezza, si può provvedere a implementare una autenticazione dei bytecodes attraverso metodi di crittografia a chiave pubblica.
Linguaggio distribuito
Linguaggio multi-threated
Ampie librerie di classi di base Il sistema Java di base fornisce le librerie di classi adatte a sviluppare numerose applicazioni di qualsiasi genere. I principali gruppi delle classi fondamentali sono:
Interazione con i browser per Internet
Prestazioni