|
Tipus de dades i operadors |
|
|
|
A través d'aquesta pràctica aprendrem quins són
els tipus de dades a Java,
a declarar-los, i a treballar amb els
operadors més importants. Encara
que a l'exposició ho presentem tot barrejat, cal tenir clar que
allò de què parlarem s'estructura de la manera següent:
- Els tipus de dades:
- Els operadors.
Fem notar encara que paral·lelament a les sentències
de control d'execució, Java
utilitza també quasi tots els operadors
de C. Com a la pràctica
anterior, si ja heu programat en C
o C++ els continguts d'aquest apartat també
us seran força familiars. |
|
|
|
Operadors i tipus de dades. |
|
|
|
Els operadors, en Java,
com en qualsevol altre llenguatge, fan certes funcions sobre els operands.
Si un operador actua sobre un sol operand,
es diu operador unari i, si opera sobre
dos operands, es diu operador binari.
- La sintaxi
i el funcionament són els mateixos que els de C
i C++:
<operador> <operand>
// Operador unari com a prefix. Primer
//
actua l'operador i després s'avalua
//
l'operand. <operand>> <operador>
// Operador unari com a sufix. Primer
//
s'avalua l'operand i, després, actua
//
l'operador. <operand_1> <operador>
<operand_2> // Operador
binari. |
- L'operador
bàsic és l'operador d'assignació
= , el
qual assigna a l'operand
de l'esquerra el valor que resulta de l'avaluació
de l'operand
de la dreta:
int num, num_1, num_2; //
Declaració de tres variables com a
//
nombres enters.
num_1 = 3; // L'operador d'assignació
' = ' assigna el valor 3 a
//
num_1
num_2 = 7; // L'operador d'assignació
' = ' assigna el valor 7 a
//
num_2
num = num_1 + num_2; // L'operador
d'assignació ' = ' assigna el
//
valor que resulta d'avaluar l'expressió
//
num_1 + num_2, a partir del funcionament
//
de l'operador aritmètic binari ' + ' en
//
actuar sobre els operands ' num_1 ' i
//
' num_2 '. |
- L'actuació dels operadors
i, finalment, la possibilitat d'avaluar les expressions
de què formen part, depèn de la perfecta coherència
dels tipus de dades que hi intervinguin.A
Java hi tenim els
següents tipus
de dades primitius i les
paraules reservades que
serveixen per declarar-los:
- byte
. Nombres enters "molt curts"
de 8 bits.
- short . Nombres
enters "curts"
de 16 bits.
- int . Nombres
enters de
32 bits.
- long . Nombres enters
"llargs" de 64
bits.
- float . Nombres reals
de 32 bits.
Precisió simple.
- double . Nombres
reals de 64
bits. Precisió doble.
- char . Caràcters
de 16 bits.
- boolean . Valors
de veritat o
falsedat: només
pot ser true o
false.
- Abans
hem esmentat els tipus de dades primitius.
Hi ha també els tipus referenciats,
anomenats així perquè els valors són apuntadors
als valors reals. Però no cal amoïnar-se!: a Java
totes les variables, siguin de tipus
primitiu o de tipus
referenciat, es criden pel seu nom.
A Java no
es manipulen apuntadors!
A Java,
com a tipus referenciats
hi ha les matrius
(arrays),
les classes
i les interfícies
(interfaces).
De la mateixa manera que farem amb les variables
de tipus primitiu, les de tipus
referenciat les cridarem
pels seus noms;per tant, no ens en preocupem
més!.
- Una primera llista d'operadors
és aquesta:
- Operadors
lògics. Els operands
han de poder-se avaluar com a boolean.
El resultat també és del tipus
boolean.
- Operador unari:
- Negació "!" .
Si exp
és true,
llavors !exp
és false.
- Operadors binaris:
- Conjunció "&&".
L'expressió exp_1
&& exp_2 només
és true si
exp_1 i
exp_2
són true
les dues. En qualsevol altre cas, és false.
- Disjunció "||".
L'expressió exp_1
|| exp_2 només és
false si
exp_1 i
exp_2 són
false
les dues. En qualsevol altre cas, és true.
- Operadors
relacionals.
Són tots binaris.
El resultat és boolean.
- Igualtat /
diferència "=="
/ "!=".
L'expressió !(exp_1==exp_2)
és equivalent a l'expressió
exp_1!=exp_2 .
- Ordre ">",
">=",
"<=",
"<".
Les expressions 3>2,
3<=3,
-5<4 i
4<=2002 són
true,
mentre que 5<=4 és
false.
- Herència "instanceof".
L'expressió obj instanceof
cls és true
si, i només si l'objecte
obj deriva
de la classe
cls.
- Operadors aritmètics.
Els operands
són nombres
i el resultat també ho és:
- Operadors binaris:
- Suma
/ resta /
multiplicació
/ divisió
"+",
"-",
"*",
"/".
L'operador "+"
també es pot fer servir per a la concatenació
de cadenes:
(strings):
"Quin bon dia "+"que
fa avui" retorna la
cadena
"Quin bon dia que fa
avui".
- Mòdul "%".
L'avaluació de n_1%n_2
retorna el residu de la divisió
entera de n_1 entre
n_2.
Així 25%5
retorna 0
i 17%4
retorna 1.
Atenció!
Els programadors de l'antic BASIC
i dels paquets de computació tipus Maple
o Mathematica
heu de saber que 2^3
no vol dir "2 elevat
a tres" i, per tant, no dóna pas
8. Per fer aquesta
operació matemàtica cal cridar al corresponent
mètode static
de la classe
java.lang.Math.
Com es fa això ja ho veurem més endavant.
- Operadors unaris:
- Canvi de signe "-".
- Increment
/ decrement "++"
/ "--".
L'expressió n++
és equivalent a n=n+1
i l'expressió n--
és equivalent a n=n-1.
- Operadors d'assignació.
Són tots binaris:
- L'operador
fonamental "=".
A l'avaluar l'expressió op_1=_op_2
, op_1
pren el valor que tingui op_2.
- Operadors d'abreviació "+=",
"-=", "*=",
"/=", "%=".
L'expressió n_1+=n_2
és equivalent a n_1=n_1+n_2.
De la mateixa manera, n_1/=n_2
és equivalent a n_1=n_1/n_2.
Encara podríem afegir a la llista els operadors
de manipulació de bytes, però de
moment ho deixem aquí. |
|
|
|
Declaració de variables: |
|
|
|
Com a C i
C++ i molts d'altres
llenguatges, cal declarar
les variables que hom hagi de fer servir. Però
cal tenir en compte algunes particularitats:
- Les variables es declaren
posant el nom
del tipus davant del nom. Darrere un nom
de tipus hom pot declarar diverses variables
del mateix tipus:
int un_nombre;
float x,y,z;
String cadena;double r,s; // Legal,
però no recomanable |
- Simultàniament a la declaració,
ja es pot assignar un valor a la variable acabada de declarar:
int un_nombre=5;
float x=3.2f,y,z;
String cadena="Bon dia";
double r,s=3.4562; |
- Els noms
de les variables són arbitraris, però ni cal que comencin
per un caràcter numèric
("0",
"1", "2",
"3", "4",
"5", "6",
"7", "8"
o "9"),
ni han de contenir caràcters que corresponen a delimitadors
(",",
".", ":",
";", "'",
""",
"(" ,")",
"[", "]",
"{" o
"}"),
operadors
("+",
"-", "*",
"/", "%",
"!", "=",
"|", "&",
"<"
o ">")
o caràcters ASCII
més enllà del 128 ("à",
"ñ",
etc.). En canvi, es pot fer servir la barra
baixa "_"
tant al principi com enmig del nom de la variable.
- Java distingeix entre
majúscules i minúscules. "laMevavariable"
i "laMevaVariable",
són noms diferents! Atenció!:
Aquest és un punt que pot confondre un principiant: el compilador
es queixa de què no heu declarat la variable "laMevavariable"
i sovint és que l'havíeu declarat com a "laMevaVariable"!
- Encara que els noms
de les variables siguin arbitraris, hi ha
convencions
respecte a això, i cal seguir-les fidelment per tal que el codi
sigui llegible:
- Els noms de
les variables haurien de començar
amb una lletra minúscula. Els noms
dels tipus referenciats, classes
i interfícies
(interfaces),
haurien de començar amb majúscula.
- Com que els noms dels tipus primitius comencen
amb minúscula, una variable de tipus primitiu pot tenir un
nom qualsevol.
- Si no hi ha una circumstància que aconselli
fer el contrari, els noms de les
variables dels tipus referenciats haurien
de ser els mateixos del nom del
tipus, però començant amb
minúscula:
Object object;
Frame frame_1,frame_2;
Canvas canvas; |
- A diferència de C,
les declaracions
poden fer-se a qualsevol punt del codi.
- La vida d'una
variable és la del fragment de codi
delimitat per "{"
i "}"
en la qual ha estat declarada. Com a conseqüencia d'això
i del punt anterior, el següent codi és incorrecte:
...
codi ...
... codi ...
if ( <condició> )
{
int n=2;
}
n=2*n; // Si "<condició>"
era false, n no haurà estat declarada!
... codi ...
... codi ... |
Caldria haver fet això altre:
...
codi ...
... codi ...
int n=0;
if ( <condició> )
{
n=2;
}
n=2*n; // L'existència de n
ara està garantida!
... codi ...
... codi ... |
- Pel fet que Java
és un llenguatge de programació
orientada a objectes (OOP,
Object Oriented Programming)
tot el codi executable ha de ser sempre entre els delimitadors "{"
i "}"i
per tant no hi ha variables
globals. Si el delimitador més pròxim
per l'esquerra és la clau ("{")
que obre la definició d'una classe,
llavors es tracta d'una variable de
classe, visible a tots els mètodes
propis de la classe:
class La_Meva_Classe {
String una_cadena; //
Variable de classe
int n=0,m=0; //
Variables de classe
void un_metode () {
int i; //
Variable que només "viu" durant l'execució
// del
mètode
i=m+n;
...
codi ...
... codi ...
}
... codi ...
... codi ...
|
|
|
Constants: |
|
|
 |
A Java
no hi ha pre-compilació i
per tant tampoc fitxers de capçalera
(clàusula #include).
Tampoc hi ha la clàusula #define
i com a conseqüència el tractament de les constants
és molt i molt diferent del que se'n fa a C,per
exemple.
Per tal de disposar de constants, la pràctica
habitual és la de definir-les com a variables
static final de certes classes
(llavors se'n diuen fields) incorporant
ja el valor que hagin de tenir. La clàusula
static vol dir que és una variable que
es demana mitjançant el nom de la classe,
no d'objectes fills i la clàusula
final implica que el valor ja no es podrà
canviar. Per exemple, el nombre p
= 3.141592... és una variable
static final de la classe
java.lang.Math. Si en algun moment del nostre
programa necessitem el valor de la constant p,
només hem de fer:
double radi=5.2, perimetre;
perimetre=2*Math.PI*radi; // Math.PI és
la "constant" pi=3.141592... |
Així, les constants matemàtiques
(e = 2.7182818284590... i p =
3.141592653589793...) són a la classe
java.lang.Math i hi són definides, respectivament,
com a public static final double E i public
static final double PI. Es criden
mitjançant Math.E i Math.PI.
Si som els programadors els qui volem definir
una constant, llavors caldrà definir-la com a variable
de classe public static final dins d'alguna
de les nostres classes i cridar-la de
la mateixa manera d'abans:
class UnaClasse {
public static final String SIGNATURA="Pau
Pi i Pons"; // Def.
... codi...
... codi...
... codi...
}
class UnaAltraClasse {
... codi...
... codi...
... codi...
System.out.println("Signat: "+UnaClasse.SIGNATURA);
// Crida
... codi...
... codi...
... codi...
} |
En general es convé que els noms de
les constants (i només aquests!) s'han d'escriure sempre
en lletres majúscules.
|
|
|
 |
En funcionament (o quasi): |
|
|
|
Farem una petita aplicació de mostra i
hi podrem trobar exemples d' ús de constants, de declaració
de variables, d'ús d'operadors... |
|
|
|
Amb JCreator
creeu el projecte Cercle
com a "empty project" i afegiu-hi
el fitxer Cercle.java,
amb aquest codi: |
|
|
|
/**
* Càlcul del perímetre, o bé de l'àrea d'un
cercle.
*
* Demostració de la utilització de declaracions de variables,
* definició de constants i d'alguns operadors
*
* Ús: java Cercle <radi> <opcio>
* "opció" és 1 (perímetre)
o 2 (àrea)
*
* @author Carles Romero
* @author Angel Solans
* @version 0.1
* @since java 1.3.1_04
*
*/
class Cercle {
/**
* El mètode static main() recull paràmetres de la consola
i els
* passa a la matriu de cadenes "args". La matriu "args"
té un mètode
* públic de la classe array, "length()", el qual, al
cridar-lo, ens
* proporciona la longitud, és a dir, el nombre d'elements, buits
o
* no, que hi ha a la matriu (array).
*/
public static void main (String[] args) {
int numParametres=args.length; //
Declaració de la variable
//
"numParametres" del tipus "int"
//
i assignació del seu valor.
double radi=0; //
Declaració de la variable "radi" del tipus
//
"double" i assignació d'un valor inicial.
switch (numParametres)
{ // Bifurcació del flux del
programa
//
en funció del nombre de
//
paràmetres introduïts per
//
l'usuari.
case
0: // L'usuari, erròniament,
no ha donat cap
//
paràmetre. El programa imprimeix els
//
missatges del cas i acaba.
//
Els textos dels missatges són constants
//
(fields) definides a la classe "Missatges".
System.out.println(Missatges.NO_PARAMETRES);
System.out.println(Missatges.RECORDA);
System.exit(0);
case
1: // L'usuari, erròniament,
ha donat un sol
//
paràmetre. El programa imprimeix els
//
missatges del cas i acaba.
//
Els textos dels missatges són constants
//
(fields) definides a la classe "Missatges".
System.out.println(Missatges.UN_SOL_PARAMETRE);
System.out.println(Missatges.RECORDA);
System.exit(0);
default:
String
sRadi=args[0]; // Declaració
de la variable
//
"sRadi" de tipus "String",
//
i assignació, com a valor,
//
del primer dels paràmetres
//
(posició 0 a la matriu args)
//
introduïts per l'usuari.
try
{ // Ara veurem si allò que
ha escrit
//
l'usuari (i que és a "sRadi") es pot
//
llegir com a "double". Fem servir el
//
mètode static de la classe Double
//
public static double parseDouble(String
//
string). EL mètode tira una excepció si
//
no pot fer la traducció.
//
El valor obtingut el posem a "radi".
radi=Double.parseDouble(sRadi);
if
(radi>0) { // El paràmetre
donat per
//
l'usuari és adequat. Li
//
imprimim un missatge, el
//
text del qual és una
//
constant (field) de la
//
classe "Missatges".
System.out.println(Missatges.RADI_BO+
sRadi);
}
else { // El paràmetre donat
per
//
l'usuari no és adequat. Li
//
imprimim un missatge, el
//
text del qual és una
//
constant (field) de la
//
classe "Missatges", i acabem
//
l'aplicació.
System.out.println(sRadi+
Missatges.RADI_NO_POSITIU);
System.exit(0);
}
}
catch (NumberFormatException e) {//
No s'ha
//
pogut
//
llegir el
//
paràmetre
//
com a
//
nombre!
//
S'imprimeix
//
un missatge
//
i s'acaba
//
l'aplicació
System.out.println(sRadi+
Missatges.NOMBRE_ESTRANY);
System.exit(0);
}
int
queFaig=0; // Declaració de
la variable "queFaig"
//
del tipus "int", i assignació d'un
//
valor inicial.
String
sQueFaig=args[1]; // Declaració
de la variable
// "sQueFaig" del tipus
// "String", i assignació,
// com a valor, del segon
// dels paràmetres (posició
// 1 a la matriu "args")
// introduïts per l'usuari.
//
try
{ // Ara veurem si allò que
ha escrit
//
l'usuari (i que és a "sQueFaig") es pot
//
llegir com a "int". Fem servir el
//
mètode static de la classe Integer
//
public static int parseInt(String
//
string).EL mètode llença una excepció si
//
no pot fer la traducció.
//
El valor obtingut el posem a "queFaig".
queFaig=Integer.parseInt(sQueFaig);
if
(queFaig>0 && queFaig<3) {//
El
//
paràmetre
//
donat
//
per
//
l'usuari
//
és
//
adequat:
//
Més gran
//
que zero
//
i ("&&")
//
més
//
petits
//
que tres.
//
Cridem el
//
mètode
//
"calcula"
calcula(radi,queFaig);
}
else { // El paràmetre donat
per
//
l'usuari no és adequat. Li
//
imprimim un missatge, el
//
text del qual és una
//
constant (field) de la
//
classe "Missatges", i acabem
//
l'aplicació.
System.out.println(sQueFaig+
Missatges.OPCIO_NO_ADMESA);
System.exit(0);
}
}
catch (NumberFormatException e) {//
No s'ha
//
pogut
//
llegir el
//
paràmetre
//
com a
//
nombre!
//
S'imprimeix
//
un missatge
//
i s'acaba
//
l'aplicació
System.out.println(sQueFaig+
Missatges.NOMBRE_ESTRANY);
System.exit(0);
}
}
}
/**
* Aquest mètode fa els càlculs demanats per l'usuari i els
imprimeix
* a la pantalla.
* Com que fem servir directament la classe "Cercle" i no una
* instància d'aquesta classe, el mètode ha de ser "static".
*/
static void calcula
(double radi,int queFaig) {
switch
(queFaig) { // Bifurcació segons
l'opció de
//
l'usuari, que és a "queFaig".
case
1: // És l'opció "1"
de l'usuari. Es calcula
//
el perímetre del cercle de radi "radi".
//
La constant pi=3.141592... és un field
//
de la classe Math.
//
S'imprimeix un missatge ad hoc, el text
// del qual és una constant
(field) de
//
la classe "Missatges".
//
Observeu com l'operador "+" uneix un
//
valor "String" (el text de "PERIMETRE_ES")
//
amb un valor del tipus "double" dins
//
del mètode println.
double
perimetre=2.0*Math.PI*radi;
System.out.println(Missatges.PERIMETRE_ES+
perimetre);
break;
case
2: // És l'opció "2"
de l'usuari. Es calcula
//
l'àrea del cercle de radi "radi".
//
La constant pi=3.141592... és un field
//
de la classe Math.
//
S'imprimeix un missatge ad hoc, el text
// text del qual és una
constant (field) de
//
la classe "Missatges".
//
Observeu com l'operador "+" uneix un
//
valor "String" (el text de "PERIMETRE_ES")
//
amb un valor del tipus "double" dintre
//
del mètode println.
double
area=Math.PI*Math.pow(radi,2.0);
System.out.println(Missatges.AREA_ES+area);
break;
}
}
}
/**
* La classe "Missatges" conté tots els missatges que
fa servir
* l'aplicació. Totes les variables són "public static
final", és
* a dir, en són fields.
*/
class Missatges {
public static final String NO_PARAMETRES=
"No
m'has donat cap parametre!";
public static final String UN_SOL_PARAMETRE=
"Nomes
m'has donat un parametre!";
public static final String RECORDA=
"Recorda
que necessito dos parametres: "+
"el
radi (un nombre positiu) i l'accio a fer "+
"('1':
perimetre, '2': area)\n";
public static final String NOMBRE_ESTRANY=
":
aixo no ho puc llegir com a nombre!\n";
public static final String RADI_NO_POSITIU=
":
aixo no es un nombre positiu!\n";
public static final String RADI_BO="El radi
que em dones es: ";
public static final String OPCIO_NO_ADMESA=
":
aquesta opcio esta fora de rang!";
public static final String PERIMETRE_ES=
"El
perimetre del cercle es: ";
public static final String AREA_ES="L'area
del cercle es: ";
}
|
|
|
 |
Executeu-lo amb paràmetres
(vegeu la part final de la pràctica 1
d'aquest mòdul) o bé, des de la finestra
de comanaments del sistema (finestra MSDOS)
mitjançant:
C:\D110src\D110ws\Modul_2\Cercle\classes>java
Cercle 1.3 1 |
Observeu el comportament de l'aplicació quan se li donen els paràmetres
-
C:\D110src\D110ws\Modul_2\Cercle\classes>java
Cercle
1 1.3 |
-
C:\D110src\D110ws\Modul_2\Cercle\classes>java
Cercle
asdf 2 |
-
C:\D110src\D110ws\Modul_2\Cercle\classes>java
Cercle
1.3 asdf |
-
C:\D110src\D110ws\Modul_2\Cercle\classes>java
Cercle
1.3 |
|
|
|
|
Com a darrer pas, observeu què
s'esdevé quan canvieu la línia
if
(queFaig>0 && queFaig<3) { |
per aquesta altra
if
(!(queFaig>2 || queFaig<1)) { |
o bé, què passa quan es canvia aquesta línia
per aquesta altra
|
|
|
|
|
|
|
|
|
 |
|
|
|
|