Enrera
Mòdul 2
Iniciació a la programació en Java
  Pràctica
1
2
3
4
4
   
Exercicis
Exercicis
 
 
  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:

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.
   
Atenció !

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:
   
Atenció !

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:
   
Atenció ! 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.

   
Pràctica 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
   
Atenció !
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

    double radi=0;

per aquesta altra

    double radi;
   
   
   
 
Amunt