Ir al Menú

Facultad de Informática

Universidad Politécnica de Madrid

Compiladores

Estás aquí: Inicio > Proyecto > Lenguaje

Introducción a Java para el Proyecto de "Compiladores"

Curso 2008/2009


Contenido:

Saltar contenido


Generalidades

Java es un lenguaje de programación diseñado inicialmente por Sun Microsystems y publicado en 1995. El lenguaje deriva de las características de los lenguajes C y C++.

Este resumen presenta las principales características de Java que hay que implementar para el Proyecto de la asignatura de Compiladores. No es necesario considerar los elementos de Java no mencionados en este resumen. Entre corchetes se dan indicaciones sobre la obligatoriedad u opcionalidad de incluir en este Proyecto algunas partes del lenguaje. Con el fin de facilitar la implementación del compilador, las características mostradas en esta página pueden no coincidir al 100% con el estándar del lenguaje, por lo que, en caso de duda, se deberá implementar el comportamiento aquí descrito.

Java es un lenguaje en el que se diferencian las minúsculas y las mayúsculas (es case sensitive). También es un lenguaje de formato libre, es decir, que se admiten espacios, tabuladores, saltos de línea y comentarios en cualquier parte del código. Cada instrucción puede ocupar una o varias líneas. Las sentencias y declaraciones terminan siempre en un punto y coma (;).

Las palabras clave que tiene el lenguaje son reservadas, aunque cada grupo de alumnos sólo ha de tener en cuenta las palabras asignadas a su grupo.

Java es un lenguaje Orientado a Objetos con estructura de bloques que se definen mediante la utilización de las llaves { }. Los nombres declarados en el interior de un bloque son locales a dicho bloque.

En Java es necesario declarar los identificadores antes de que se utilicen. Además, hay que implementar el Compilador de Java considerando que es un lenguaje con recursividad, por lo que cualquier método puede ser recursivo. No se permite la definición de métodos anidados. El paso de parámetros es por valor para los tipos básicos y por referencia para los tipos compuestos.

No hay que considerar la existencia de destructores, la herencia, las excepciones ni los paquetes. Los programas a desarrollar en lenguaje Java serán de los que se denominan Standalone, no los denominados Java Applets ni Java Servlets.

Estructura de un Programa

Para el Proyecto de Compiladores debe considerarse que un programa en Java estará compuesto por un único fichero que ha de tener una serie de Clases, con atributos y métodos definidos, siendo uno de ellos el método principal.

En este enlace se muestra un ejemplo de un fichero en Java para el Proyecto de Compiladores.

Programa Principal

El programa principal (el que se ejecutará al arrancar el programa) será un método especial, de una de las clases, que recibe el nombre de main, que no puede llevar argumentos, tiene que ser público y tiene que ser de tipo void:

class ClasePrincipal
{
   public void main (void)
   {
      código_del_programa_principal;
   }
}

Comentarios

En Java se admiten dos tipos de comentarios [sólo hay que implementar uno de ellos]:

No se admiten comentarios anidados. Los comentarios pueden ir colocados en cualquier parte del código donde pueda ir un espacio:

/* Comentario de bloque */
// Comentario de línea

Constantes

El lenguaje dispone de varios tipos de constantes, de las cuales solamente habrá que tener en cuenta las siguientes:

Enteros

Las constantes enteras se escribirán en notación decimal sin signo (por ejemplo, 159, 0). El ensamblador que se utilizará dispone de números enteros de 2 bytes (con signo), por lo que el máximo entero será el 32767 [es obligatorio implementar los enteros].

El lenguaje también dispone de constantes enteras en notación octal (usando como prefijo un cero: 052) y en notación hexadecimal (usando como prefijo un cero y una equis: 0x1E4). [La implementación de la notación octal y hexadecimal es opcional.]

Cadenas de Caracteres

Las constantes de cadena consisten en una secuencia de caracteres encerrados entre comillas ("¡Hola, mundo!"). Las cadenas utilizan internamente el carácter nulo (cuyo código ASCII es 0) como carácter de fin de cadena. Puede aparecer cualquier carácter imprimible en la cadena [es obligatorio implementar las cadenas constantes].

Para representar caracteres especiales se utiliza una secuencia de escape, que comienza mediante el carácter barra inversa y va seguido de un carácter. Algunos de estos caracteres especiales son el salto de línea (\n), el tabulador (\t), el carácter nulo (\0), las comillas dobles (\") o el carácter de barra inversa (\\). Por ejemplo, la constante "¡Hola, \"Compiladores\"!" representa a la cadena ¡Hola, "Compiladores"!. [Esta implementación de las secuencias de escape es opcional.]

Lógicas

En Java existen dos constantes lógicas: true y false [es opcional implementar las constantes lógicas].

Operadores

Este lenguaje presenta un conjunto de operadores con los que escribir distintas expresiones. Además, se pueden utilizar los paréntesis para agrupar subexpresiones.

Operadores Aritméticos

Son los operadores que permiten realizar la suma, resta, producto, división y módulo: +, -, *, / y % [obligatorio implementar al menos uno]. Se aplican sobre datos enteros, proporcionando un resultado entero.

También existen los operadores más y menos unarios: +, - [implementación opcional].

Operadores de Relación

Son los operadores que permiten realizar las comparaciones de igual, distinto, menor, mayor, menor o igual, mayor o igual: ==, !=, <, >, <= y >= [obligatorio implementar al menos uno de los operadores]. Se aplican sobre datos enteros y proporcionan un resultado lógico.

Operadores Lógicos

Representan las operaciones de conjunción, disyunción y negación: &&, || y ! [obligatorio implementar al menos uno]. Se aplican sobre datos lógicos y devuelven un resultado lógico.

Operadores de Incremento y Decremento

Permiten auto-incrementar (++) o auto-decrementar (--) el valor de un identificador entero (ambos pueden actuar como prefijos o como sufijos) [algunos grupos tienen que implementar al menos uno de los cuatro]. Se aplican sobre identificadores enteros y devuelven un resultado entero modificando también el valor del identificador. Ejemplo:

a = j++; /* si j valía 5, ahora a == 5 y j == 6 */
a = ++j; /* si j valía 5, ahora a == 6 y j == 6 */

Operadores de asignación

Permiten realizar asignaciones simples o realizando simultáneamente una operación: =, +=, -=, *=, /= y %= [todos los grupos tienen que implementar la asignación simple (=) y algunos grupos deberán implementar uno de los otros operadores]. Ejemplo:

n += m;	/* es equivalente a n = n + m; */

Operador Condicional

El operador condicional (condición ? exp1: exp2) permite obtener un valor basándose en una condición [implementación obligatoria solo para algunos grupos]. Si la condición es cierta, devuelve exp1; en caso contrario, devuelve exp2. Ejemplo:

max = (a > b) ? a : b;	// Si a > b entonces max == a; en otro caso, max == b

Operador de Acceso a Miembros de una Clase

El operador punto (.) permite utilizar los miembros de una clase. Ejemplo:

c.a= c.m(); /* accede al atributo a y al método m de la clase c */

Operador de Acceso a Elementos de un Vector

El operador corchete ([ ]) permite utilizar los elementos de un vector [implementación obligatoria sólo para algunos grupos]. Ejemplo:

a= v[i+1]; // accede al elemento i+1 del vector v y copia su valor en a

Precedencia de Operadores

En la tabla siguiente se muestra la precedencia de los operadores con el siguiente significado: los operadores del mismo grupo tienen la misma precedencia y, conforme se desciende por la tabla, la precedencia disminuye. En cualquier caso, el uso de paréntesis permite alterar el orden de evaluación de las expresiones [es obligatorio para todos los grupos implementar el uso de paréntesis y tener en cuenta las precedencias de los operadores utilizados].

Precedencias de los Operadores
Operadores Significado Asociatividad
.
()
[]
Referencia a miembro de clase
Llamada a método
Referencia a elemento de vector
Izquierda a derecha
!
++
--
+
-
Negación lógica
Autoincremento
Autodecremento
Más unario
Menos unario
Derecha a izquierda
*
/
%
Producto
División
Módulo
Izquierda a derecha
+
-
Suma
Resta
Izquierda a derecha
>
>=
<
<=
Mayor
Mayor o igual
Menor
Menor o igual
Izquierda a derecha
==
!=
Igual
Distinto
Izquierda a derecha
&& Y lógico Izquierda a derecha
|| O lógico Izquierda a derecha
? : Operador condicional Derecha a izquierda
=
op=
Asignación simple
Asignación con operación
Derecha a izquierda

Identificadores

Los nombres de identificadores están formados por cualquier cantidad de letras, dígitos y subrayados (_), siendo el primero siempre una letra, un subrayado o un dólar ($). Ejemplos: a, a3, A3, Sueldo_de_Trabajador, _9_9__, $a...

Como ya se ha dicho, el lenguaje es dependiente de minúsculas o mayúsculas, por lo que los nombres a3 y A3 hacen referencia a identificadores distintos.

Declaraciones

En el lenguaje Java se exige la declaración de identificadores antes de poder usarlos. No se admite la redeclaración de nombres en un mismo ámbito. La declaracion de variables se realiza dentro de los métodos (variables locales).

Para realizar una declaración de una variable, se escribe el nombre del tipo seguido del nombre de la variable, finalizando en un punto y coma (;).

Se puede poner una lista de variables separadas por comas [esta declaración múltiple es opcional].

Tipo var0;
Tipo var1, var2, var3; /*se declaran tres variables*/

Opcionalmente, puede inicializarse una variable en la misma instrucción de la declaración, colocando detrás del nombre de la variable el operador de asignación (=) seguido de un valor constante [la inicialización de variables es opcional].

Tipo var0= valor0;
Tipo var1= valor1, var2, var3= valor3; /*se inicializan dos variables*/

Si se intenta usar una variable sin haberle dado un valor, el compilador deberá dar un error.

Las declaraciones podrán aparecer en cualquier parte del bloque de un método. Es decir, pueden aparecer sentencias y declaraciones mezcladas.

Tipos de Datos

El lenguaje dispone de distintos tipos de datos, que pueden ser clasificados en Tipos Básicos (o elementales) y Tipos Compuestos (que se forman a partir de tipos básicos).

Tipos Básicos

Se deben considerar sólo los siguientes tipos de datos básicos: entero, lógico y vacío.

El lenguaje no permite conversiones entre tipos.

Tipos Compuestos

Cada grupo tendrá que implementar uno de estos tipos compuestos, basándose en la opción que le corresponda. En los ejemplos se va a hacer uso de elementos del lenguaje que se explicarán posteriormente.

Vectores

Para usar un vector es obligatorio declarar una variable de tipo vector y a continuación definir su tamaño. Su declaración es de las siguientes formas [implementación obligatoria para algunos grupos, aunque solo es necesario implementar uno de los formatos]:

Tipo var [tamaño];	//declaración de vector
Tipo [tamaño] var;	//declaración de vector

El valor tamaño debe ser un valor entero constante que especifica la dimensión del vector. Los índices del vector van desde 0 hasta tamaño - 1, ambos incluidos. Los elementos del vector pueden ser enteros o lógicos [no hay que implementar vectores de tipos compuestos].

Para acceder a un elemento del vector se usan los operadores corchete ([ y ]) con el índice en su interior. El índice del vector puede ser cualquier expresión entera válida:

int [24] x;   /* Se ha declarado el vector x de 24 elementos enteros */ 
int w[31], v[31];
/* Se han declarado los vectores v y w de 31 elementos enteros */ 
v[26]= 2;          /* se almacena un 2 en la posición 26 */ 
x[3]= 13;          /* se almacena un 13 en la posición 3 */
w[1]= v[x[3] * 2]; /* se almacena un 2 en la posición 1 */

Con un vector se pueden realizar las siguientes operaciones: consultar y modificar sus elementos (a través de su índice), asignar una variable tipo vector a otra (siempre que tengan la misma dimensión y tipo de elementos) y ser argumento de un método.

La asignación de vectores realiza una copia de todos los elementos de una variable vector en otra variable vector.

Con respecto a los métodos, los vectores se pueden pasar como argumentos por referencia (copiando su dirección), pero un método no puede devolver un vector. En la declaración del método debe indicarse su tipo y su nombre seguido o precedido [solo hay que implementar una de ellas] de los corchetes con la dimensión del vector:

void p (int z[30], int y[40], int [50] x)
// declara un método que recibe como parámetros por referencia tres vectores 
{
  int a[30], i;
  a= z; // se realiza una copia de todo el vector z en a
  for (i=8; i<20; i++)
    z[i]= a[i - 1] + y[5 + i] + x[i * 2];
}

Cadenas

Java dispone de una forma específica para declarar cadenas mediante el tipo String. La sintaxis para declarar una variable cadena es [implementación obligatoria para algunos grupos]:

String variableCadena;

De esta manera se declara una variable capaz de almacenar una cadena de caracteres. También puede inicializarse una variable cadena en la declaración [implementación opcional]:

String cadena_declarada;
String cadena_inicializada= "cadena";

Se permiten operaciones de asignación de cadenas (bien variables cadena, bien asignar una constante cadena a una variable), envío como argumento a un método por referencia, impresión de una cadena en pantalla (mediante la función print) y la lectura de cadenas del teclado (mediante la función read).

La asignación de cadenas realiza una copia de todos los caracteres de una variable cadena en otra variable cadena.

Con respecto a los métodos, las cadenas se pueden pasar como argumentos por referencia (copiando su dirección), pero un método no puede devolver una cadena. En la declaración del método debe indicarse su tipo y su nombre:

void copia (String x, String y)
{
  String u, aux;
  read (u);    /* lee una cadena del teclado */ 
  aux = u;     /* copia la cadena u en aux */
  print (aux); /* imprime la cadena */
  x= y;        /* copia la cadena y en x */
}
void pp (void)
{
  String s, u;
  copia (s, "Java");
  u= "Lenguaje ";  /* la variable u contendrá la nueva cadena */ 
  print (u);   /* escribe la cadena "Lenguaje " */
  print (s);   /* escribe la cadena "Java" */ 
}

[Nota: Como simplificación para su implementación, puede asumirse un tamaño fijo máximo para cada cadena.]

Instrucciones de Entrada/Salida

La función print (expresión_entera) evalúa la expresión e imprime en pantalla su resultado. Por ejemplo:

a= 50; print (a * 2 + 16); /* imprime: 116 */

La función print (cadena) imprime en pantalla la cadena. La cadena puede ser una constante de tipo cadena [obligatorio para todos los grupos] o una variable de tipo cadena [obligatorio solo para los grupos con variables de tipo cadena]. Por ejemplo:

a= "Adiós"; print ("Hola"); print (a); /* imprime HolaAdiós */

La función print () imprime en pantalla un salto de línea. Por ejemplo:

a=50; print(a * 2 + 16); print(" Euros"); print();
/* imprime: 116 Euros y luego salta de línea */

La función read (variable_entera) lee un número entero del teclado, asignándose el valor leído a la variable recibida como parámetro. Por ejemplo:

int a; read (a); print (a * a); /* imprime el cuadrado del número leído */

La función read (variable_cadena) lee una cadena del teclado, asignándose el valor leído a la variable recibida como parámetro [obligatoria sólo para los grupos que tengan el tipo cadena]. Por ejemplo:

String a; read (a); print (a); /* imprime la cadena leída */

Sentencias

De todo el grupo de sentencias del lenguaje Java, se han seleccionado para ser implementadas en el Proyecto las que aparecen a continuación [opcional u obligatoriamente, según se indique en cada caso]:

Sentencias de Asignación

Existe una sentencia de asignación en Java, mediante el operador de asignación = [es obligatorio implementar la sentencia de asignación]. Su sintaxis general es la siguiente: identificador, igual y expresión; asigna al identificador el resultado de evaluar la expresión (los datos deben ser del mismo tipo):

i= 8 + 6;

También se permite que a la izquierda de la asignación aparezca un atributo [obligatorio] o un elemento de un vector [obligatorio para los grupos que tengan vectores]:

v[i]= 5;
a.b= i;

Sentencia de Llamada a un Método

Esta sentencia permite invocar la ejecución de un método previamente definido [implementación obligatoria].

La llamada a un método se realiza mediante el nombre del método seguido de los argumentos actuales (separados por comas) entre paréntesis si existen (si no tiene argumentos, hay que poner los paréntesis). Se puede llamar a métodos de la propia clase simplemente con su nombre, o a métodos de otras clases colocando previamente el nombre del objeto:

p1 (5);        // llamada a un método propio con un argumento entero 
o.p2 ();       // llamada sin argumentos a un método del objeto o  
p3 (b, i - 8); // llamada con dos argumentos a un método propio

Los parámetros actuales en la llamada tienen que coincidir en número y tipo con los parámetros formales de la declaración del método. Si el método devuelve un valor, también podrá incluirse una llamada a un método dentro de cualquier expresión; si la llamada no se realiza en una expresión, el valor devuelto se perderá:

b= 1 + o.fun1 (9); /* llamada a un método de o con un argumento entero */ 
c= b + fun2 (b, fun3() - 8); /* llamada con dos argumentos a un método, 
                siendo fun3, una llamada a otro método sin argumentos */
fun2 (5, c); /* el valor devuelto por fun2 se pierde */

Sentencia de Retorno de un Método

Java dispone de la sentencia return para finalizar la ejecución de un método y volver al punto desde el que fue llamado [implementación obligatoria]. Si el método es del tipo void, éste terminará cuando se ejecute la instrucción return o al llegar al final del cuerpo del método. Si el método no es de tipo void, éste finalizará su ejecución, devolviendo el valor obtenido al evaluar la expresión que acompañe a la sentencia return; en este caso, el tipo de la expresión de la sentencia return debe coincidir con el tipo del método.

int SumaAlCuadrado (int a, int b) /*método entero*/
{
  int j;  /* variable local a SumaAlCuadrado */
  j= a + b;
  return j * j;
  /* Como es un método entero, tiene que llevar una expresión entera. *
   * El método finaliza y devuelve el valor de la expresión           */
}
void pro (int x)
{
  x= SumaAlCuadrado (x - 1, x);
   /* x contendrá el valor devuelto por el método: (x+x-1)^2 */
  if (x > (194/2))
    return; // como es un procedimiento, no puede llevar expresión;
            // finaliza la ejecución del procedimiento 
  print (SumaAlCuadrado (x, x));
} /* finaliza la ejecución del procedimiento */

Sentencia Condicional

Selecciona la ejecución de una de las secuencias de sentencias que encierra, dependiendo del valor correspondiente de una condición de tipo lógico. Tiene dos formatos [implementación obligatoria de ambos para los grupos que les corresponda]:

Si la condición se evalúa como cierta, se ejecutan las sentencias1; en caso contrario, se ejecutan las sentencias2 (si el programador las ha escrito). Cada uno de estos grupos de sentencias podrá ser bien un bloque de sentencias encerradas entre llaves o bien una única sentencia:

if (a > b)
  c= b;
else 
{
  c= a;
  if (fin)
    print ("adiós");
}

Sentencia Repetitiva while

Esta sentencia permite repetir la ejecución de unas sentencias basándose en el resultado de una expresión lógica [implementación obligatoria para algunos grupos]. La sintaxis es: while (condición) sentencias.

Se evalúa la condición y, si resulta ser cierta, se ejecutan las sentencias (que puede ser una única sentencia o bien un bloque de sentencias encerradas entre llaves). Este proceso se repite hasta que la condición sea falsa:

while (n <= 10) 
{
    n= n + 1;
    print (n);
} /* mientras que n sea menor o igual que 10... */

Sentencia Repetitiva do while

Esta sentencia permite repetir la ejecución de las sentencias del bucle mientras se cumpla una condición [implementación obligatoria para algunos grupos]. La sintaxis es: do sentencias while (condición);. En esta instrucción se puede colocar una única sentencia o bien un bloque de sentencias encerradas entre llaves.

Se ejecutan las sentencias; seguidamente se evalúa la condición y, si resulta ser cierta, se ejecutan de nuevo las sentencias. Este proceso se repite hasta que la condición sea falsa:

do {a++; c *= b;} while (a < b);

Sentencia Repetitiva for

Esta sentencia for permite ejecutar un bucle según una condición compleja [implementación obligatoria para algunos grupos]. La sintaxis es: for (inicialización; condición; actualización) sentencias. La inicialización debe ser una sentencia de asignación o nada; la condición debe ser una expresión lógica; y la actualización puede ser una asignación, un autoincremento o autodecremento [para los grupos que tengan esta opción] o estar vacía. Las sentencias pueden estar formadas por un bloque delimitado por llaves o por una única sentencia.

El funcionamiento de este bucle es como sigue:

  1. Se ejecuta la inicialización
  2. Se evalúa la condición
  3. Si la condición es falsa, se abandona la ejecución del bucle
  4. Se ejecutan las sentencias
  5. Se ejecuta la actualización
  6. Se vuelve al paso 2.
for (i = 1; i < 10; i++) f *= i;

Sentencia de Selección Múltiple

Esta sentencia selecciona una ejecución de unas sentencias basándose en el resultado de una expresión [implementación obligatoria para algunos grupos]. La sintaxis de la sentencia de selección múltiple es:

switch (expresión)
{
  case valor1: sentencias1
  case valor2: sentencias2
  /* . . . */
  default: sentenciasn;
}

Su funcionamiento es como sigue: Se evalúa la expresión (que debe ser de tipo entero), se busca el valor que coincida con el resultado (los valores tienen que ser constantes enteras) y se ejecutan sus sentencias asociadas. Una vez ejecutadas, se continúa la ejecución de todas las sentencias asociadas a todos los valores que se encuentren a continuación hasta el final del switch. Si no se encuentra el valor, se ejecutan las sentencias asociadas a default, si el programador la ha incluido. [El default es opcional para la implementación.]:

switch (dia)
{
   case 1: print ("lunes");
   case 2: print ("martes");
   case 3: print ("miércoles");
   case 4: print ("jueves");
   case 5: print ("viernes");
   default: print ("fiesta");
} /* si dia == 4, se imprimirá: juevesviernesfiesta */

Sentencia break

Esta sentencia aborta la ejecución de un bucle o un switch [implementación obligatoria para los grupos que tengan switch]:

switch (dia)
{
   case 1: print ("lunes"); break;
   case 2: print ("martes"); 
   case 3: print ("miércoles"); break;
   case 4: print ("jueves"); break;
   case 5: print ("viernes"); break;
   default: print ("fiesta");
} /* si dia == 4, se imprimirá: jueves */

Clases

Java es un lenguaje orientado a objetos, por lo que cuenta con la posibilidad de definir y utilizar clases. Una clase es una estructura que puede contener datos miembro (atributos) y funciones miembro (métodos). Los atributos son variables declaradas en el seno de la clase y los métodos son funciones de la clase. Es necesario declarar cada clase antes de poder utilizarla. Para definir una clase se pone la palabra class, el nombre y los miembros entre llaves:

class nombre
{
   miembros;
}

La definición de los miembros es como sigue:

class Nombre	// declara la clase denominada Nombre
{
   Tipo atributo;	// un atributo es como una variable local a la clase
			// y es visible por todos los métodos de la clase
   Tipo método (parámetros)	// un método es una función de una clase
   {
      sentencias;
   }
   Nombre (parámetros)	// un método con el mismo nombre de la clase
	// se llama constructor y se ejecuta automáticamente
	// al definirse una variable del tipo de la clase.
	// Solo puede haber un constructor por clase y no devuelve nada
   {
      sentencias;
   }
}

Para utilizar una clase, es necesario primero declarar una variable (un objeto) de dicha clase y crearla mediante la operación new (que ejecutará al constructor de la clase, si existe). Los miembros de una clase se pueden usar desde el interior de la propia clase haciendo referencia directamente al nombre del miembro. Si se desea usar un miembro de otra clase, hay que usar el nombre del objeto, un punto y el nombre del miembro:


Nombre var;  // declara var como de tipo Nombre. 
             // A esta variable se le llama objeto de la clase
var = new Nombre (parámetros); // se crea una instancia de la clase (se define)
             // y se llama al constructor (si lo hay) con los parámetros
var.atributo = valor;    // modo de acceder a un atributo
var.método (argumentos); // modo de llamar a un método

Con un objeto de una clase se pueden realizar las siguientes operaciones: consultar y modificar sus atributos, llamar a sus métodos y asignar un objeto a otro objeto de la misma clase (copiando sus atributos de uno a otro). Un objeto no se puede enviar como argumento a un método, ni puede ser el tipo de retorno de un método, ni puede ser a su vez atributo de otra clase.

Control de Acceso a Miembros

La característica de la ocultación de la información se encuentra implantada en Java mediante el control de acceso a los miembros de las clases. Para controlar el acceso a los miembros, éstos pueden declararse como públicos o privados, utilizando las correspondientes palabras reservadas:

Delante del tipo de un atributo o de un método, puede colocarse una de las dos palabras de control de acceso. Si no se indica un control de acceso, se supone que los miembros son privados. Un método de una clase puede acceder a todos los demás miembros (sean públicos o privados) directamente por su nombre.

Atributos

Los atributos son variables locales declaradas en el seno de la clase. La declaración de un atributo es similar a la declaración de variables. El siguiente ejemplo muestra la declaración de una clase con cuatro atributos:

class Ejemplo
{
  public int i;      // atributo i entero público
  private boolean b; // atributo b lógico privado
  public String s;   // atributo s cadena público
  int v [5];         // atributo v vector de enteros privado
}

Métodos

Es necesario definir cada método antes de poder utilizarlo. La definición de un método se realiza indicando el tipo, el nombre y, entre paréntesis, los tipos y nombres de los argumentos (si existen). Tras esta cabecera va un bloque (delimitado por llaves) que contiene las declaraciones de variables locales al método (si existen) y las sentencias del método:

Tipo nombreFun (lista de argumentos)
{
   declaraciones;
   sentencias;
}

El Tipo es uno de los tipos básicos del lenguaje (en el caso del constructor de una clase, no se pone ningún tipo). La lista de argumentos (que puede estar vacía y, en este caso, se ponen los paréntesis con la palabra void en su interior) consta del tipo y el nombre de cada parámetro formal. Si hay más de un argumento, éstos se separan por comas. Los argumentos se pasan por valor para los tipos básicos y por referencia para los tipos compuestos.

Los métodos pueden recibir como parámetros cualquiera de los tipos básicos del lenguaje (entero o lógico), así como el tipo compuesto que le haya correspondido a cada grupo.

Los métodos pueden devolver cualquiera de los tipos básicos del lenguaje (entero, lógico o vacío). Un método del tipo void indica que dicho método no retorna ningún valor.

Java admite recursividad. Todos los grupos de trabajo han de considerarla en su implementación. Cualquier método puede ser recursivo, es decir, puede llamarse a sí mismo.

El lenguaje Java no permite la definición de métodos anidados. Esto implica que dentro de un método no se puede definir otro método.

Dentro de un método se tiene acceso a las variables locales que se declaren en dicho método, a sus argumentos y a los miembros de su clase. Así mismo, desde un método se pueden utilizar miembros públicos de otras clases, para lo que hay que usar un objeto de dichas clases. Si en un método se declara una variable local o un argumento con el mismo nombre que un atributo, éste último no es accesible desde dicho método.

class Ejemplo
{
 int factorial (int x) 
   /* se define el método recursivo entero con un parámetro entero */
 {
   if (x > 1)
     return x * factorial (x - 1);
   else
     return 1;
 }
 public void Suma (int aux [50], int fin)
   /* se define el procedimiento Suma que recibe un vector  
      por referencia y un entero por valor */ 
 {
   for (i= 1; i < fin; i= i + 2)
     print (factorial (aux [i - 1]));
 }
}

El método constructor recibe un tratamiento especial, pues tiene el mismo nombre que la clase y solo puede ser llamado mediante la instrucción de creación de un objeto (new). Puede recibir parámetros, pero no devuelve absolutamente nada, ni siquiera void. Finalmente, tiene que ser siempre público. Por ejemplo:

class Ejemplo
{
 int ej;
 public Ejemplo (int x, String s, int j) 
 {
   print (s);
   ej= x + j;
   for ( ;x < j; x=x+2)
      ej += x;
 }
}
//...
Ejemplo ee;
ee= new Ejemplo (3, "Hola", 99);

Más Información sobre el Lenguaje

Hay que tener en cuenta que para el Proyecto de Compiladores no es necesario tener un conocimiento total de este lenguaje. Tan solo hay que incorporar el funcionamiento del pequeño subconjunto del lenguaje necesario para implementar las partes comunes a todos los grupos que se han explicado aquí, así como las partes obligatorias de cada grupo. Por tanto no hay que incluir todas las características, variantes y elementos que tiene el lenguaje real.

Aquí se tiene un ejemplo de un fichero que incorpora la mayoría de las funcionalidades descritas en esta página, a modo de ejemplo adicional para facilitar su compresión.

En cualquier caso, se puede encontrar más información sobre Java en la página de referencias, en los libros que hay en la Biblioteca de la Facultad (se puede usar el buscador de la UPM), así como en cualquier libro, manual o documentación del lenguaje (buscando en librerías como Amazon). También se pueden encontrar otras fuentes de información realizando búsquedas en la Web o en los siguientes enlaces:

La Web

W3C:

XHTML 1.1 válido

CSS 2.1 válido

Accesibilidad:

P. 3 (UNE 139803)

AAA (WCAG 1.0)

Web Master

Accesos:

Contador de accesos desde octubre-06

Mapa

Último cambio:

30-octubre-2008