Interfaz Grafica de Usuario - Figuras

Ya vimos como crear una ventana y como utilizar JPanel para dibujar atraves de objetos Graphics. A continuación profundizaremos en el uso de Graphics para crear figuras complejas, Antes, te presento a la clase Color del paquete java.awt. Color nos permite "crear" o mejor dicho especificar un color para algún objeto o componente. La clase color cuenta con Objetos finales para utilizar colores predefinidos como: Color.red Color.blue Color.white etc... Es posible, tan bien, especificar muchos mas colores a traves de valores RGB, dichos valores pueden ser de 0.0 a 255 o de 0 a 1.0, poniendo estos valores en el constructor de Color al crear el objejo. ej:                         Color cPersonal = new Color(255,128,0); //en este caso creamos el color naranja acá tienes una pagina con valores RBG que puedes utilizar en la creación de colores personalizados. http://www.december.com/html/spec/colordec.html También se puede agregar color a una figura directamente a través de su método "setColor" propio de objetos gráficos. a continuación veremos esto.

Creación de ovalos rellenos.

linea 1 - package especifica el paquete en el que he creado mis clases. no creo que haga falta explicar esto.
lineas 3 a 6 - las importaciones necesarias para poder dibujar y crear el contenedor tal cual hicimos en la entrada anterior. solo se ha añadido la clase Random. con la cual podemos generar números al azar entre un determinado conjunto.
la linea 10 - hacemos la sobre-escritura OBLIGATORIA del método paintComponent() para poder dibujar en el contenedor. si te fijas aparece un mensaje de advertencia del IDE (de color amarillo) este mensaje se debe a que el el método paintComponent() esta siendo sobrescrito. puedes dejarlo tal cual (el mensaje) o si te posicionas sobre el mismo te dará la opción de poner una anotación "@Override" con lo que se saldrá la advertencia. esto es solo para identificar los métodos sobrescritos. 
linea 14 - creamos un objeto Random para poder crear colores y especificar posiciones al azar.
linea 15 - creamos un for que itere 4 veces, para crear 4 óvalos.
linea 17 - mediante el parámetro de Graphics g creamos un nuevo color con valores RGB al azar mediante
numeros al azar entre 0 y 255. Para esto es necesario poner un    new Color dentro del parámetro de setColor(). y especificar tres valores numéricos. En este caso los tres valores son al azar.
linea 18 - utilizamos fillOval() método que nos permite crear un ovalo relleno del color previamente especificado.
     El metodo fillOval( ); recibe 4 argumentos; los primeros dos indican las posiciones X e Y          respectivamente y los otros dos indican el largo en X y el alto en Y.  En realidad lo que se crea es un
 cuadrado y el ovalo  se crea al dibujarlo dentro del cuadrado tocando cada centro de las rectas. de la siguiente manera : (los valores de las coordenadas son de la esquina superior derecha del cuadrado imaginario, esto se aplica a cualquier figura que creemos.)
Si te fijas, en el ejemplo puse los primeros dos argumentos como objetos Random que pueden
ser de 0 a 230, puse esos valores para que cuando se cree el ovalo no se salga de la ventana que es de ancho 300.
esta clase es igual que la que creamos en la entrada pasada. creamos una clase que herede de JFrame y especificamos los atributos básicos de la ventana. seguimos añadiendo setLotationRealativeTo(null); para que la ventana aparezca en el medio de la pantalla. también especificamos a serResizable(null) para que no pueda ser dimensionada. En el main instanciamos el objeto JFrame.y le añadimos nuestra clase Dibujos para que muestre nuestros dibujos en la ventana.
Como las `posiciones y colores de los óvalos son al azar, cada vez que ejecutemos nuestra clase tendrá resultados diferentes.
Ahora para probar un curioso y atractivo efecto, haz lo siguiente. Pon después de la llave de cierre del for una llamada al método repaint( ); el efecto te agradara.

Otros métodos de Graphics 

- fillRoundRect (int x, int y, int anchura, int altura, int anchuraArco, int alturaArco);
     Dibuja un rectángulo relleno con esquinas redondeadas, en el color que este especificado, con el ancho y      la altura especificados. los valores de anchuraArco y alturaArco determinan el grado de redondez de las        esquinas.
- draw3DRect (int x, int y, int anchura, int altura, boolean b);
    Dibuja un rectángulo tridimensional relleno en caso de que el argumento booleano sea true, 
- clearRect();
   Dibuja un rectángulo relleno con el color de fondo actual. lo que permite eliminar (mejor dicho cubrir) áreas especificas de una  imagen.
Esta es otra aplicación que utiliza figuras para crear un "smile", solo se ha modificado la clase Dibujos.
-nota que el color se ha añadido mediante el metodo setColor y se ha especificado colores solidos (declarados como finales en la clase Color.).
-Para la boca se utilizaron dos ovalos, primero uno negro y luego uno amarillo levemente mas arriba para cubrir la mayor parte del negro dejando asi solo una linea como sonrisa.
nota que los métodos fill y en general cualquiera que pueda utilizar colores toma el color que se haya especificado antes, hasta que se indique otro.

Ejercicio propuesto:::

Crea la siguiente figura utilizando solo drawLine();
Como ayuda, te sirve tener el alto y el ancho mediante los metodos getWidth(); getHeight(); y de alli comenzar a restarle a los lados.
Tambien puedes crear unas lineas centrales para guiarte y después quitarlas.

Interfaz gráfica de usuario.(Creación de una ventana y dibujos)

La interfaz gráfica de Usuario (GUI por sus siglas en ingles) En Java es un capitulo extenso que iremos viendo a medida que avanzamos en los temas referente a este lenguaje. Puedes encontrar libros completos sobre las GUI's en java,
Generalmente a la programación de interfaz gráfica se le denomina swing,  Swing es, hoy en dia, la API (si no sabes lo que es una API lee esto http://en.wikipedia.org/wiki/Application_programming_interface) principal para programación a nivel gráfico y es parte de la JFC (Java Fundation Classes) Osea, se integra de manera nativa en Java. Swing es la evolución -por decirle así- de la antigua AWT (Abstract windows Toolkit) que también es un conjunto de clases diseñadas para implementar la interfaz gráfica en java.
El nacimiento de Swing de debe a las falencias obvias que se fueron dando en AWT en su implementación, algunas de ellas fueron:

 - awt dependía de la plataforma en que se desarrollaba para mostrar sus componentes, es decir, se mostraba una barra distinta en windows y en unix lo que traía problemas con los esquemas y no funcionaba efectivamente para el objetivo primordial de java; la portabilidad extrema entre plataformas.

- Al depender íntimamente del sistema en que se ejecuta, awt añade funcionalidades básicas o mínimas para poder operar correctamente. aunque esto tiene un beneficio; los componentes de awt son mas livianos que los de Swing.

Por el contrario, Swing se implementa 100% a través del codigo volviéndose independiente de la plataforma en que se ejecuta. Swing a su vez es mucho mas personalizable de AWT al tratarse de clases insertadas en arboles amplios de herencia que pueden conbinarse sin romper los hilos del código. Swing permite emular estilos de ventanas como los de windows classic, windows en versiones posteriores, mac y linux entre otros, a través de su LOOK AND FEEL. una de las ventajas principales de swing es que permite a los programadores proveer su propia implementación de apariencia sin la necesidad de grandes cambios en el código, esto gracias a que swing apunta a la uniformidad visual de sus componentes.


  JFrame

Comenzaremos nuestra discusión acerca de una de las cosas mas emocionantes de cualquier lenguaje (me refiero a la interfaz gráfica y diseño en general) con dibujos simples sobre un panel desplegado en pantalla, dejaremos de lado el terminal de netbeans para comenzar con las ventanas y gráficos.

Antes de comenzar a dibujar en un panel tenemos que comprender el sistema de coordenadas en Java.
De manera automática Java nos ubica el punto 0,0 en la parte superior izquierda de la pantalla o ventana dependiendo del objeto que trabajemos. Aclaro esto, cuando creamos un componente, por ejemplo un botón, y le damos la coordenada 100,250. no nos referimos a la coordenada 100,250 de nuestro monitor sino del componente donde vaya a encajar ese botón. vale aclarar esto.
 
La primera coordenada es el eje X y se refiere a la posición horizontal de la ventana o componente y la segunda coordenada se refiere al eje Y y se refiere a la posición vertical de la ventana o componente, en el que cada punto es en realidad un pixel.


Lo primero que debemos crear es una ventana o mejor dicho un marco que contenga los componentes que iremos añadiendo a ella, esto lo haremos atraves de la clase JFrame.




Como podemos ver en esta imagen JFrame es una version extendida de la clase Frame del paquete AWT, como muchos de los componente del paquete javax,swing  JFrame añadió características avanzadas a los componentes básicos de Frame tal y como lo explique al principio de esta entrada. 
Para crear un marco  con JFrame vamos a crear una clase que extienda de esta.



linea 1 - importamos la clase JFrame del paquete javax.swing. lo que nos permitira ocupar a JFrame cuando queramos dentro de esta clase.
linea 3 - hacemos que nuestra clase extienda de JFrame (extends) con esto tenemos los constructors, métodos normales y variables de JFrame listas para ser sobrecargados o llamados. Es importante ya le dice al programa que nuestra clase es una subclase de JFrame con lo que podemos crear nuestros propios atributos para la ventana que construiremos.
linea 5 - Creamos un constructor de nuestra clase. de vital importancia ya que debemos hacer un llamado del constructor de JFrame.
linea 7 - atraves de super llamamos al constructor de JFrame con un argumento de tipo String, este argumento sera el titulo de la ventana. JFrame tambien tiene otras tres versiones de su constructor sobrecargadas. Lo mas comun es que llamemos a la que recibe un parametro String como en este caso o en su defecto podemos llamar simplemente a la version por defecto atraves de super(); sin mas.
Recuerda que podemos utilizar super para llamar al constructor de JFrame por que hemos especificado que nuestra clase extiende de esta ultima.
linea 8 - el metodo setSize de JFrame recibe dos argumentos (largo, alto) en este caso la ventana sera de 300  x 300. es uno de los métodos esenciales para la creación de ventanas o contenedores ya que determina el tamaño inicial del mismo. veremos que este tamaño puede ser o no modificable ya sea en expansión o contracción.
linea 9 - setVisible este metodo (de JFrame) establece si la ventana sera visible, para ello recibe un argumento de tipo booleano, true si queremos que se vea la ventana y false en caso contrario. este método no es implícito del frame por lo que en caso de no llamarlo por olvido o lo que sea, la ventana no se mostrara.
linea 10 - setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); sirve para que al presionar sobre la X de la ventana osea cuando queremos cerrarla el proceso termine y no continúe ejecutándose en memoria. EXIT_ON_CLOSE es una variable de tipo int, declarada como final y static. osea el método setDefaultCloseOperation recibe un parámetro int para determinar si que debe hacer con la ventana.
lo mejor es siempre establecer este parámetro como en el ejemplo.

Con estos métodos dentro del constructor ya hemos creado la primera ventana!!!!

linea 15 - se crea un objeto de Ventana1 dentro del método main para que se ejecute el constructor. el resultado de la ejecución es la ventana que aparece a un constado del código. como podemos ver es un marco vacio con un encabezado y los respectivos botones de minimizar y maximizar. notese que la ventana tiene la misma apariencia de windows 7 que es el sistema donde se esta ejecutando.



Esta es otra manera de crear la ventana, hay libros donde lo hacen así, la única diferencia con el código anterior es que los métodos son llamados a través de la instancia de la clase directamente en el main. Ambos códigos son completamente validos y operativos.

tal vez hayas notado que la ventana aparece al costado superior izquierdo de la pantalla, pues bueno Java nos permite posicionar donde queramos la ventana para ello debemos hacer una llamada al metodo

setLocationRelativeTo();

JFrame hereda este método de la clase Window del paquete java.awt. y nos permite especificar en que lugar de la pantalla aparecerá nuestra aplicación a traves de un parametro de tipo component. por ahora solo utilizaremos como parámetro  - null - lo que nos deja la ventana en el centro de la pantalla.

setLocationRelativeTo(null);

debemos localizar este metodo junto a los otros que pusimos en el constructor o donde este llamado el objeto JFrame.


JPanel

Ya creamos un marco de ventana para nuestra aplicacion de dibujo, ahora crearemos el "lienzo" en el que pondremos nuestros dibujos. para ello ocuparemos la clase JPanel.





JPanel es un contenedor simple que nos permite añadirle objetos como botones, barras, dibujar sobre el , etc...
Al igual que con JFrame debemos hacer que nuestra clase extienda de JPanel. Como sabemos una clase no puede extender de mas de una clase a la vez por lo que se suelen crear dos clases a la hora de crear una aplicación que dibuje. Aunque si se puede hacer en una sola clase. a ver si se te ocurre como!!!

JPanel y las clases que extiendan de ella cuentan con un método llamado paintComponent() que el sistema llama automáticamente cada vez que se utiliza un objeto JPanel. y es necesario que nosotros lo declaremos pues de lo contrario los objetos de JPanel podrían no mostrarse. 

paintComponent requiere un argumento de tipo Graphics que sirve para crear dibujos y otras graficas. 
La primera linea dentro del método paintComponent debe ser:

super.paintComponen(g);

esto asegura que el panel se muestre apropiadamente en la pantalla. por lo tanto quedaria asi.

paintComponent(Graphics g)
{
super.paintComponent(g);
......
......
}

ahora a partir del objeto Graphics g podemos llamar a los metodos apropiados para dibujar ovalos, cuadrados, letras etc...



lineas 1 y 2 - se hacen las importaciones de las clases que utilizaremos para dibujar. JPanel y Graphics.
linea 4 - hacemos que nuestra clase herede de JPanel (extienda). 
linea 6 - hacemos una sobre escritura del método paintComponent pasandole un argumento Graphics para poder crear dibujos o lo que queramos (la g del parámetro es solo el nombre del argumento, se pone g para saber que es un objeto Graphics pero puede ser cualquiera).
linea 8 - se hace la llamada directa al método de la superclase, a traves de super.  esto se hace para asegurar que se muestre correctamente en pantalla. yo he probado ejecutando los códigos sin esta llamada y no he tenido problemas al mostrar los componentes, pero aun así, es mejor asegurarse, ademas que esta llamada no genera desgaste de memoria.

Los metodos getWidth() y getHeight(); devuelven el ancho y la altura del panel en el momento respectivamente. en caso de que agrandemos o disminuyamos el tamaño de la ventana y por lo tanto del panel, se llama implícitamente a un método llamado repaint(); que vuelve a dibujar el objeto en el panel.


la linea 11 - llama al metodo drawLine(x, y, x ,y);  Este método dibuja una linea recta y recibe 4 argumentos de coordenadas. los primeros dos especifican el primer punto y las otras dos el punto final, luego ambos puntos se unen formando la linea recta.
En este caso le pasamos (0 , 0 , ancho, alto); por lo que la linea inicial queda en la esquina superior izquierda
(0, 0) y el segundo punto queda en la esquina inferior derecha (ancho, alto).
Recordemos que las variables ancho y alto reciben el tamaño del panel en el momento. osea si el panel es de (300, 300) esas son las coordenadas de ancho y alto.
la linea 12 - pone drawLine(0 , alto, ancho , 0); con lo que ponemos el primer punto en la esquina inferior izquierda (0 , alto) recordar que alto tiene el valor del tamaño de alto del panel, por lo que queda de 0 horizontalmente y con alto para abajo.

acá el código de la clase ejecutora. 



Este es el código de la clase que usamos para ejecutar el panel, si te fijas es practicamente la misma que utilizamos para crear el marco. es mas ¡¡¡es la misma!!! solo tiene algunas variaciones.

en la linea 10 - llamamos al método setLocationRelativeTo(null); que como la dije se utiliza para dejar la ventana en el medio de la pantalla.

linea 17 - se crea un objeto Panela que por consiguiente es un objeto JPanel.
linea 18 - se utiliza el método add de JFrame (recordar que Ventana1 por herencia es un objeto JFrame) y añadimos el panel para que se muestre en la ventana, sino se hace esto a través de  "add"  se mostrara solo el marco como en el primer ejemplo.

Ahora si agrandamos y disminuimos el tamaño de la ventana una vez ya ejecutada veremos como las lineas se vuelven a dibujar quedando siempre de esquina a esquina.




 













Objetos, Composición y miembros static

En java Casi todo es un objeto, la única excepción como ya se ha explicado son los tipos primitivos.
Los modificadores de acceso (public private, protected, friendly) nos permiten definir el alcance y desde
donde se puede acceder a los objetos. Es una buena practica de programación que establezcamos los métodos y variables importantes de una clase como private, por lo general se declaran así cuando son objetos a los que no se deben acceder directamente, para ello establecemos -a su vez- métodos public para modificar dichos valores. por ejemplo:

private int saldo; //variable declarada como private

public void agregarSaldo(int valor)
{
   if(valor >0)
  {
   saldo = saldo+valor;
  }else{
  System.out.println("debe ingresar un monto mayor  a 0");
  }
}//fin método modificarSaldo

Como podemos ver acá tenemos una variable <<saldo>> que esta como private para que no pueda
ser modificada desde ningún otro lugar que no sea la misma clase en que se declara, y a su vez tenemos un método <<agregarSaldo>> que es la encargada de modificar el saldo, siempre y cuando se cumpla una condición, en este caso que el valor ingresado sea mayor que 0. también podríamos tener un método
restarSaldo que solo permita restar un monto no mayor a 200000 como es el caso de los cajeros automáticos chilenos. Con estos métodos ponemos un limite en el acceso a lo que seria un valor importante como saldo.

ejercicio sugerido: Crea una clase Cuenta, con metodos deposito, giro y consulta, cada metodo debe validar sus datos y enviar mensajes apropiados en caso por ejemplo que de se intente hacer un giro mayor al saldo disponible. la variable saldo debe ser private y los memtodos public. crea el metodo main en otra clase.

this

Todos los objetos pueden acceder a una referencia de si mismos a través de la palabra clave this 
ej:

private int saldo;
   
   public void agregarSaldo(int saldo)
   {
   this.saldo = this.saldo + saldo;
   }


En este pequeño fragmento de código utilizamos la palabra "this" para hacer referencia a la variable saldo de
la clase, pues en caso contrario estaríamos haciendo referencia a la variable local "saldo" del método.
con this también podemos diferenciar entre dos variables en las relaciones de herencia, en caso de que nos vemos a declarar variables con el mismo nombre tanto en la superclase como el la subclase.

otro uso de this, es para referenciar a un constructor de la misma clase, por ejemplo:

public class referenciaThis{
  
    referenciaThis(int n1)
   {
    this(2,5); //esta llamada debe ser siempre la primera linea del constructor
   }
   
   referenciaThis(int n1, int n2)
   {
   

   }
}//fin de la clase refenciaThis.


Para llamar a un constructor dentro de otro, en la misma clase utilizamos simplemente this sin el nombre
del constructor y debemos asegurarnos que esta llamada sea la primera declaración en el constructor. poner un punto después de this para llamar a un constructor es un error de sintaxis.
¿pero como sabemos cual es el constructor al cual llamamos? La llamada se distingue a través de sus paramentos, en este caso como ponemos 2 y 5 estamos indicándole a this que llamamos al constructor de dos parámetros.
es un error auto-invocar a un constructor, es decir hacer que un constructor se llame a si mismo, esto produce recursividad infinita.
también cable aclarar que esta llamada a un constructor a través de this, es solo valida dentro de otro constructor y no de un método normal.

Un constructor puede llamar a los metodos de una clase simplemente utilizando su nombre y la lista de parámetros adecuada, pero debes tener en cuenta que el constructor esta inicializando el objeto (la clase) por lo que las variables de instancia pueden no estar en un estado consistente. Para evitar errores lógicos no realices llamadas a métodos que muestren o modifiquen variables de instancia que no han sido inicializadas

Composición

La capacidad de una clase de contener referencias de otra clase como miembros se conoce como Composición. por ejemplo una clase Calculadora debería tener referencia a la clase Numeros para realizar sus operaciones. La composición es una de las herramientas de re-utilización de software mas poderosas, ya que podemos crear objetos que sean útiles para múltiples objetos futuros.. por ejemplo podemos tener una clase Fecha que nos devuelva la fecha actual, y dicha clase la podriamos utilizar al interior de una clase agendaDespertador que utilice a la clase Fecha para comprobar si tenemos citas o recordatorios para la fecha actual.

Ejemplo:
Creamos una clase Triangulo que puede ser instanciada en cualquier parte donde necesitemos un triangulo. este ejemplo básico puede ser ampliado para obtener mas especificaciones del triangulo como el perimetro o la superficie.

public class Triangulo {

private int  altura, b, posX, posY;  
   
    Triangulo(int altura, int b) //constructor encargado de crear el triangulo e inicializar las variables
    {
    this.altura = altura;
    this.b = b;
    }
   
    int areaTri()
    {
    return (altura*b)/2;       //retorna el area
    }
   
    void setPosicion(int pX, int pY) //establece la posicion en el plano
    {
    posX = pX;
    posY = pY;
    }
   
    String getPosicion()  //retorna la posicion como un String con formato
    {
    String pos = ("X="+posX+",Y="+posY);  
    return pos;
    }
}//FIN DE LA CLASE


public class PruebaFiguras {

  public static void main(String []args)
  {
    Triangulo t1 = new Triangulo(15, 10); //crea el primer triangulo
    t1.setPosicion(100, 100);
    System.out.printf("%s\n%s%d\n%s%s\n\n","Triangulo 1","Area :",t1.areaTri()
            ,"Posicion :",t1.getPosicion());
   
    Triangulo t2 = new Triangulo(22,18); //crea el segundo triangulo
    t2.setPosicion(300, 100);
    System.out.printf("%s\n%s%d\n%s%s\n\n","Triangulo 2","Area :",t2.areaTri()
            ,"Posicion :",t2.getPosicion());
  }  //fin del metodo main
}//fin de la clase PruebaFiguras

*******************
la salida es la siguiente:

Triangulo 1
Area :75
Posicion :X=100,Y=100

Triangulo 2
Area :198
Posicion :X=300,Y=100

GENERACIÓN CORRECTA (total time: 0 seconds)

Este simple ejemplo nos demuestra que una clase "es una fabrica de objetos" en este caso objetos triángulos que podríamos utilizar en cualquier momento para saber un área, un perímetro o incluso posicionarlo en un plano o interfaz gráfica. Al crear objetos que sean re-utilizables ahorraremos tiempo en escribir codigo que ya puede estar probado y depurado de antemano.


Miembros static

Cada objeto mantiene una copia de todas las variables de instancia de clase, en algunos casos solo es necesario compartir una copia de alguna variable entre todos los objetos de la misma clase, con el objetivo de que los cambios escritos en dicha variable sean vistos por cualquier objeto de las clases.
Para estos fines utilizamos los denominados campos static o mejor llamadas variables de clase 

Veamos un ejemplo con datos static. Suponga que tenemos un videojuego con Marcianos y otras criaturas espaciales. Cada Marciano tiende a ser valiente y deseoso de atacar a otras criaturas espaciales cuando sabe que hay al menos otros cuatro Marcianos presentes. Si están presentes menos de cinco Marcianos, cada Marciano se vuelve cobarde. Por lo tanto, cada uno de ellos necesita saber el valor de cuentaMarcianos. Podríamos dotar a la clase Marciano con la variable cuentaMarcianos como variable de instancia. Si hacemos esto, entonces cada Marciano tendrá una copia separada de la variable de instancia, y cada vez que creemos un nuevo Marciano, tendremos que actualizar la variable de instancia cuentaMarcianos en todos los objetos Marciano. Las copias redundantes desperdician espacio y tiempo en actualizar cada una de las copias de la variable, además de ser un proceso propenso a errores. En vez de ello, declaramos a cuentaMarcianos como static, lo cual convierte a cuentaMarcianos en datos disponibles en toda la clase. Cada objeto Marciano puede ver la cuentaMarcianos como si fuera una variable de instancia de la clase Marciano, pero sólo se mantiene una copia de la variable static cuentaMarcianos. Esto nos ahorra espacio. Ahorramos tiempo al hacer que el constructor de Marciano incremente a la variable static cuentaMarcianos; como sólo hay una copia, no tenemos que incrementar cada una de las copias de cuentaMarcianos para cada uno de los objetos Marciano.



Las variables static tienen alcance a nivel de clase. Los miembros public static de una clase pueden
utilizarse a través de una referencia a cualquier objeto de esa clase, o califi cando el nombre del miembro con el nombre de la clase y un punto (.), como en Math.random(). Los miembros private static de una clase
pueden utilizarse solamente a través de los métodos de esa clase. En realidad, los miembros static de una
clase existen a pesar de que no existan objetos de esa clase; están disponibles tan pronto como la clase se carga en memoria, en tiempo de ejecución. Para acceder a un miembro public static cuando no existen objetos de la clase (y aún cuando sí existen), se debe anteponer el nombre de la clase y un punto (.) al miembro static de la clase, como en Math.PI. Para acceder a un miembro private static cuando no existen objetos de la clase debe proporcionarse un método public static, y para llamar a este método se debe califi car su nombre con el nombre de la clase y un punto. (Las clases, por ejemplo Math son importadas indirectamente atrevez del árbol de herencia implícito de java, Recuerda que toda clase en java hereda de la clase Object.)