Herencia, Reutilización y La Clase Object



Una de las características esenciales de la programación orientada a objetos (POO) es la herencia, ya que esta es una poderosa herramienta de reutilización de software; en ella podemos utilizar los componentes de una clase ya existente de forma total o parcial, dándonos la oportunidad, incluso, de mejorar ese código o utilizarlo tal cual. Una de las ventajas que podemos nombrar es que permite la reutilizacion de software probado y depurado por otros programadores, disminuyendo asi el tiempo del desarrollo. Para utilizar la herencia debemos crear una clase que "Extienda o herede" de otra, la clase plantilla en este caso es conocida como SUPERCLASE y la clase que extiende de esta es la SUBCLASE, en algunos lenguajes como C++ la superclase es conocida como la clase base y la subclase como la clase derivada. Podemos pensar este tema de la siguiente manera; una superclase es una idea  general sobre un objeto y la subclase es mas especifica y trata con los detalles. por consiguiente podemos afirmar que la herencia se trata de una especialización de las diferentes clases heredadas. En java hay dos tipos de herencia, la directa y la indirecta; en la directa, nosotros mismos somos los encargados de especificar la superclase de la nuestra a través de la palabra extends (ya veremos como usarla), La herencia indirecta es aquella que se hace de forma implicita solo por el hecho de crear un clase, por ejemplo al crear un clase, de manera predeterminada esta extiende (hereda) de la clase Object (la clase mas alta en el arbol). ¡¡ java es un lenguaje de herencia simple !! es decir solo puede extender de una clase a la vez. Mas adelante cuando veamos poliformismo e interfaces veremos como podemos usar otras tecnicas para emular lo que hace la herencia multiple.

LA relación "Es un" y "Tiene un"

La relacion "es un" habla simpre de herencia y puede explicarse atraves de una frase simple como "es auto ES UN medio de transporte" como puedes darte cuenta auto es un subtipo de medio de transporte, en este caso podriamos decir que medio de transporte es la superclase y auto es la subclase:

caracteristicas (atributos) de Medios de Transporte: 
    -trasladan cosas, personas, animales.
    -puede ser aéreo, terrestre, marítimo
    -recorre un camino con punto de inicio y final.
    
características(atributos) de Autos;
    -trasladan cosas, personas, animales.
    -es terrestre.
    -recorre un camino con punto de inicio y final.
    -tiene un volante-
    -puede ser manual o automático
    -acelera y frena
Como puedes ver "medios de transporte" podría considerarse como una plantilla que podria definirse a si misma y a sus atributos, pero también serviría para crear especificaciones de si misma, a través de la creación de clases que describan por ejemplo a; autos, aviones, helicópteros, barcos etc...
En este caso describimos auto para hacer notar que comparte características de medios de transporte, pero no podríamos declarar un auto simplemente como medio de transporte ya que tiene detalles que no podrían especificarse en ella, como por ejemplo ; si es automático o manual, que es terrestre, etc... no podríamos poner como atributos estas cosas en medios de transporte ya que tenemos, por ejemplo, un avion que no es terrestre.
En contraste la relación "tiene un " hace referencia a la composición (que ya veremos en detalle) es decir a los atributos propios de la clase, por ejemplo un auto "tiene un" máximo de velocidad. por lo general estos atributos de clase suelen especificarse mediante "static"

Alcance de las variables y clases en la herencia
ya hablamos en otras entradas sobre los modificadores de acceso, Es importante a esta altura recordarlo para utilizar lo aprendido en el campo de la herencia.
hablamos sobre los miembros public de una clase que pueden ser vistos desde cualquier otra clase, del mismo u otro paquete. tambien hablamos sobre los miembros private que solo son visibles desde la clase en que se declaran ESTE TIPO DE VARIABLES NO SE HEREDAN.  y miembros protected que tienen un nivel de acceso intermedio, estos miembros pueden ser vistos por las clases heredadas y por las demas clases del mismo paquete en que se declaran.
*A pesar de no tenemos visibilidad desde una subclase d elos miembros private de la superclase, si podemos modificar dichas variables a través de métodos public heredados de la superclase.
*Se declaran variables private para proteger al máximo los valores de las mismas de la intrucion no permitida.
*El compilador establece de forma automática a  Object como la clase predeterminada en caso de no encontrar alguno otra clase declarada como superclase de la nuestra.
ej:
public class Animal {
    private String tipo;//se establece como private para que no pueda ser cambiada desde la subclase
    
    public void establecerNombre(String tipo)//establece el nombre del animal
    {
    this.tipo = tipo;
    }
    
    public void mensaje()
    {
    System.out.println("Tu animal es un "+tipo);
    }
    
    public void camina()
    {
    System.out.println(tipo+" camina");
    }
    
    public void vuela()
    {
    System.out.println(tipo+" vuela");
    }
}
en esta clase, puse metodos publicos, uno para establecer el nombre o tipo de animal y otras para mostrar mensajes respecto al tipo de animal
public class Perro extends Animal{ //subclase de animal
    
    Perro() //creamos un constructor para poder llamar  a los metodos de la superclase
    {
    this.establecerNombre("perro");  //establesco el tipo de animal 
    this.mensaje(); //llamamos solo a los metodos que utilizaremos de la super clase
    this.camina();
    }
    
    public static void main(String[]args)
    {
    Perro ini = new Perro();
    }
}
por ejemplo, en la superclase a hay un método que se llama vuela, como nuestro animal (perro) no vuela, no utilizaremos este método, pero podríamos crear otra clase llamada "Pajaro"  que si va a necesitar el metodo vuela(). 
(En la superclase podriamos haber puesto infinidad de metodos para aludir a acciones)
la salida de este programa seria asi:
run:
Tu animal es un perro
perro camina
BUILD SUCCESSFUL (total time: 0 seconds)
La herencia no solo nos permite llamar a los métodos o atributos de una clase, sino que tambien podemos sobre escribirlos
por ejemplo, en la superclase animal esta el método
public void mensaje()
    {
    System.out.println("Tu animal es un "+tipo);
    }
Al cual llamamos desde el constructor de la subclase Perro, pero que pasa si quisieramos modificar ese mensaje?? pues podríamos hacerlo asi, Desde la clase perro sobreescribimos el metodo mensaje() lo que nos quedaría asi.
public class Perro extends Animal{
    
    Perro()
    {
    this.establecerNombre("perro");
    mensaje();
    this.camina();
    }
    public void mensaje()
    {
    System.out.println("tu animal es el mejor amigo del hombre");
    }
    
    public static void main(String[]args)
    {
    Perro ini = new Perro();
    }
}
//al hacer esto estamos sobrescribiendo el metodo mensaje() (el compilador nos mostrara un mensaje de advertencia diciendonos que estamos sobreescribiendo un metodo de la super clase). fijense que en el constructor de perro elimine el this y llame al metodo solo con el nombre.
la salida de este programa seria esta :
run:
tu animal es el mejor amigo del hombre
perro camina
BUILD SUCCESSFUL (total time: 1 second)
Como tercera opcion tambien podemos sobreescribir un metodo de la superclase y al mismo tiempo llamar a dicho metodo a traves de la palabra clave super. Con super podemos llamar al metodo o constructor de la superclase, para ello debemos estar en el metodo sobrescrito o en el constructor. Para ello modificaremos unas simples lineas de nuestra clase perro.
public class Perro extends Animal{
    
    Perro()
    {
    this.establecerNombre("perro");
    mensaje();
    this.camina();
    }
    public void mensaje()
    {
    super.mensaje();
    System.out.println("tu animal es el mejor amigo del hombre");
    }
    
    public static void main(String[]args)
    {
    Perro ini = new Perro();
    }
}
 //Si te fijas, este codigo es casi igual al anterios, lo unico diferente es que tiene la sentencia super.mensaje();
lo cual hace un llamado al metodo original, lo ejecuta y despues continua con el codgio dentro del metodo sobreescrito.
La salida seria la siguiente.
run:
Tu animal es un perro
tu animal es el mejor amigo del hombre
perro camina
BUILD SUCCESSFUL (total time: 0 seconds)
si te fijas, se ha agregado a la salida la linea de código del método mensaje original al cual llamamos mediante super.
*Es un error de compilación sobrescribir un método con un modificador de acceso más restringido; un método public de la superclase no puede convertirse en un método protected o private en la subclase; un método protected de la superclase no puede convertirse en un método private en la subclase. Hacer esto sería quebrantar la relación es un, en la que se requiere que todos los objetos de la subclase puedan responder a las llamadas a métodos que se hagan a los métodos public declarados en la superclase. Si un método public pudiera sobrescribirse como protected o private, los objetos de la subclase no podrían responder a las mismas llamadas a métodos que los objetos de la superclase. Una vez que se declara un método como public en una superclase, el método sigue siendo public para todas las subclases directas e indirectas de esa clase.
*Llamar a un metodo o constructor de la superclase con un numerod e argumentos y tipos diferentes de los requeridos produce un error de compilacion.
*Es recomendable no usar  variables protected, en vez de eso utiliza  variables private y especifica metodos public para modificar dichas variables.
*si queremos llamar a un metodo de la superclase desde un metodo sobrescrito de la subclase, debemos asegurarnos de llamarlo con la palabra clave super y un punto. ya que de no hacerlo se genera una recursividad infinita, en la que el metodo se llame asi mismo, hasta agotar la memoria.
miMetodo() //metodo sobreescrito de la superclase
{
miMetodo(); // sin super, provoca recursividad ya que el metodo se llama a si mismo.
}
asi se hace correctamente.
miMetodo()
{
super.miMetodo(); //llama al metodo de la super clase.
}
La recursividad infinita e suna poderosa herramienta que veremos mas adelante.
La clase Object
Como ya hemos dicho varias veces todas las clases en java heredan de la Clase Object, y con ello obtienen sus 8 metodos, puedes probarlo creando una clase e instanciandola, pones el nombre de la instancia y un punto y te saldran los 11 metodos heredados de object.
clone()
Este método protected, que no recibe argumentos y devuelve una referencia Object, realiza una copia
del objeto en el que se llama. Cuando se requiere la clonación para los objetos de una clase, ésta debe
sobrescribir el método clone como un método public, y debe implementar la interfaz Cloneable
(paquete java.lang). La implementación predeterminada de este método realiza algo que se conoce
como copia superfi cial: los valores de las variables de instancia en un objeto se copian a otro objeto del
mismo tipo. Para los tipos por referencia, sólo se copian las referencias. Una implementación típica
del método clone sobrescrito sería realizar una copia en profundidad, que crea un nuevo objeto para
cada variable de instancia de tipo por referencia. Hay muchos detalles sutiles en cuanto a sobrescribir el
método clone. Puede aprender más acerca de la clonación en el siguiente artículo:
java.sun.com/developer/JDCTechTips/2001/tt0306.html
equals()
Este método compara la igualdad entre dos objetos; devuelve true si son iguales y false en caso contrario.
El método recibe cualquier objeto Object como argumento. Cuando debe compararse la igualdad
entre objetos de una clase en particular, la clase debe sobrescribir el método equals para comparar
el contenido de los dos objetos. La implementación de este método debe cumplir los siguientes requerimientos:
• Debe devolver false si el argumento es null.
• Debe devolver true si un objeto se compara consigo mismo, como en objeto1.equals( objeto1 ).
• Debe devolver true sólo si tanto objeto1.equals( objeto2 ) como objeto2.equals( objeto1 )
devuelven true.
• Para tres objetos, si objeto1.equals( objeto2 ) devuelve true y objeto2.equals( objeto3 )
devuelve true, entonces objeto1.equals( objeto3 ) también debe devolver true.
• Si equals se llama varias veces con los dos objetos, y éstos no cambian, el método debe devolver true
de manera consistente si los objetos son iguales, y false en caso contrario.
Una clase que sobrescribe a equals también debe sobrescribir hashCode para asegurar que los objetos
iguales tengan códigos de hash idénticos. La implementación equals predeterminada utiliza el operador
== para determinar si dos referencias se refi eren al mismo objeto en la memoria. La sección 30.3.3
demuestra el método equals de la clase String y explica la diferencia entre comparar objetos String
con == y con equals,
finalize()
El recolector de basura llama a este método protected  para
realizar las tareas de preparación para la terminación en un objeto, justo antes de que el recolector de
basura reclame la memoria de ese objeto. No se garantiza que el recolector de basura vaya a reclamar un
objeto, por lo que no se puede garantizar que se ejecute el método finalize del objeto. El método debe
especifi car una lista de parámetros vacía y debe devolver void. La implementación predeterminada de
este método sirve como un receptáculo que no hace nada.
getClass()
Todo objeto en Java conoce su tipo en tiempo de ejecución. El método getClass devuelve un objeto de la clase Class (paquete java.lang), el cual contiene
información acerca del tipo del objeto, como el nombre de su clase (devuelto por el método getName de
Class). Puede aprender más acerca de la clase Class en la documentación de la API en línea, en java.
sun.com/javase/6/docs/api/java/lang/Class.html.
hashCode()
 Una tabla de hash es una estructura de datos  que relaciona a un objeto,
llamado la clave, con otro objeto, llamado el valor. Cuando inicialmente se inserta un valor en una
tabla de hash, se hace una llamada al método hashCode de la clave. La tabla de hash utiliza el valor de
código de hash devuelto para determinar la ubicación en la que se debe insertar el valor correspondiente.
La tabla de hash también utiliza el código de hash de la clave para localizar el valor correspondiente
de la misma.
notify()
notifyAll()
wait()
Los métodos notify, notifyAll y las tres versiones sobrecargadas de wait están relacionados con el
subprocesamiento múltiple. En versiones recientes de Java, el modelo
de subprocesamiento múltiple ha cambiado en forma considerable, pero estas características se siguen
soportando.
toString()
Este método devuelve una representación String de un objeto. La
implementación predeterminada de este método devuelve el nombre del paquete y el nombre de la clase
del objeto, seguidos por una representación hexadecimal del valor devuelto por el método hashCode del
objeto.

String, una mirada más detallada.



La clase String representa a las cadenas de caracteres y como tal no hemos de olvidarnos que es un objeto, por lo tanto es del tipo por referencia, siempre que puedo hago hincapié en la diferencia entre los primitivos y los de referencia pues es importante ya que cada tipo tiene características que lo hacen único  así como las herramientas para trabajar con ellos, por ejemplo en la comparación.
Una variable de tipo primitivo como un int puede compararse a través de los operadores binarios (binarios porque necesitan dos operandos)

int num = 5, num2 = 10;

num == num2;  //compara la igualdad entre num y num2

pero este tipo de comparación no es valida para un String, en realidad el compilador no dará error si se utiliza el operador == para comparar dos String, pero si mostrara la advertencia y esto es porque == compara a nivel binario los datos como si se tratase de un valor primitivo, esto puede generar errores en tiempo de ejecución difíciles de encontrar y depurar, sobretodo si estamos comparando variables con cadenas de caracteres entrantes a través del teclado.
en vez de eso utilizaremos un método de la clase String llamado equals. lo utilizaremos como ejemplo en un if.

String nombre1 = "horacio";
String nombre2 = "carlos";

if(nombre1.equals(nombre2))
{
System.out.println("Son iguales");
}

para utilizar equals ponemos el nombre de la variable a comparar, un punto y equals() entre los parentesis va la variable que se comparara con la primera. Este metodo (equals) devuelve un valor booleano, true si son iguales y false si son diferentes.
Si te fijas, llamamos al método atraves de un punto despues del nombre de la variable al igual como lo hacemos cuando instanciamos una clase (clase instancia = new clase();) y esto es porque cuando creamos un String en realidad estamos creando una variable de aquella clase. por eso podemos acceder a los métodos de la clase String simplemente poniendo un punto después de la variable.

Comparar String de distintos tamaños.

String tiene un metodo llamado compareTo que es heredado desde una interfaz generica llamada Comparable, ya veremos de que se trata esto. Lo importante es que podemos usar el metodo recien nombrado en cualquier cadena de caracteres,
compareTo devuelve 0 si los String son iguales, un valor negativo si la primera palabra es lexicograficamente menor y un valor positivo si la palabra es lexicograficamente mayor

ej:

String hola = "hola";
String hola1 = "hola como estas";
   
   if(hola.compareTo(hola1) > 0) //compareTo devuelve un numero positivo si hola es mayor que hola1
   {
       System.out.println("mayor");
   }
   else if(hola.compareTo(hola1)<0) //compareTo devuelve un numero negativo si hola es menor que hola1
   {
      System.out.println("menor"); //este es el que se ejecuta ya que se cumple el encabezado del if. osea, el
   }                                            //numero que devulve compareTo es menor que 0  
   else if(hola.compareTo(hola1)==0) //compareTo devuelve 0 si ambos String son iguales
   {
       System.out.println("igual");
   }

El resultado de esto seria "menor". ya que hola es lexicograficamente menor que hola1.


Comparar String con mayusculas y minusculas.

A veces sera necesario comparar Strings que se diferencien solo por sus mayus o minusculas. Para ello utilizares el metodo equalsIgnoreCase(). Este metodo funciona igual que el equals.

String nombre = "chuña";
String nombre2="CHUÑA";

if(nombre.equalsIgnoreCase(nombre2))
{
System.out.println("Los nombres son iguales");.
}

Esto es muy util cuando tenemos una aplicación que pide ingreso de datos y no necesitamos ser tan estrictos con ello.


El metodo toString

El método toString es heredado por todos los objetos en java a través de clase Object (la clase mas alta en el árbol, por decirle así)  y nos permite mostrar al objeto como un String. por ahora solo lo veremos en arreglos. por ejemplo tenemos un pequeño problema, cada vez que queremos mostrar un arreglo (que es un objeto) debemos llamar a un for o a un while  y mostrar sus valores de forma individual. La solución para esto fue presentada en java 5 a traves de la clase Arrays con ayuda del método toString.
por ejemplo, supòngamos que deseamos imprimir el siguiente arreglo como un String.

int arregloA[] = {22,15,103,1,896};
para hacerlo debemos importar java.util.Arrays; , la clase quedaria algo asi.
///////////////////////////////////////////////////////
import java.util.Arrays;

public class saludos {
    
   public static void main(String[]args)
   {
   int variables[]={22,15,103,1,896};
   System.out.println(Arrays.toString(variables));
   }
}
////////////////////////////////////////////////////
La salida seria esta:
run:
[22, 15, 103, 1, 896]
GENERACIÓN CORRECTA (total time: 0 seconds)
 También se puede guardar el String de retorno del método Arrays.toString( ); en un String diferente.
por ejemplo
String resultante = Arrays.toString(variables);
Lo que va entre el paréntesis es el arreglo a imprimir. 


Otros metodos.... (Lo que esta entre paréntesis al lado del nombre del método es el tipo de valor de retorno del metodo)

length();   (int)// retorna el largo del String como un valor entero.
ej:
String dato ="vocales";
int vDato = dato.length();

por consiguiente vDato valdrá 7. Si contamos el largo de un String y este tiene espacios entre medio estos igual cuentan ya que esos espacios cuentan como caracteres también.


indexOf(); (int) //retorna la posición donde encuentre el String o el char pedido en su lista de parámetros
ej:
String cadena = "the beatles";
int busca = cadena.indexOf("beatles");

entonces busca ahora tendrá el valor 4 ya que encuentra a "beatles" a partir de la posición 4, recordar que se empieza a contar de 0 y que cuenta el espacio en blanco. en caso de no encontrar al String o char.


replace(); (String, char)//reemplaza un caracter (char) por otro especificado en la lista de parametros.
ej:
String cadena = "Pata";
String NCadena;
Ncadena = cadena.replace('a' , 'o');

Ncadena ahora tiene el String "Poto" ya que se reemplazaron las 'a' por las 'o'


replaceAll(); (String)// reemplaza un fragmento completo del String o el String completo.
ej:
String nombre = "juanin juanjarri";
nombre = nombre.replaceAll("juanjarri","larrain");

nombre, entonces, queda como "juanin larrain";

toUpperCase();(String) //cambia todas las letras a mayusculas
ej:
String nombre = "maria mercedes";
String nombre = nombre.toUpperCase();

ahora String contiene "MARIA MERCEDES" Cambien esta la opción inversa, es decir, convertir todo a minúsculas a través de toLowerCase();


subString(); (String) // toma un fragmento de un String y lo almacena en la misma o otra variable.
ej:
String frase = "resident evil es un buen juego"
frase = frase.subString(20,30);

frase ahora valdria "buen juego";

Transformaciones desde y hacia String

int valor = Integer.parseInt(String)                 // Pasar de String a int 
String resultado = Integer.toString(12345)      // Pasar de int a String 
String resultado = Double.toString(12345.25)  // Pasar de double a String 
String resultado = Float.toString(12345.70)     // Pasar de float a String 
String hilera = Character.toString(caracter)   //Pasar de caracter a hilera 


*los valores entre parentesis son solo ejemplos.

Temario de Preguntas 1


Preguntas:


1_ ¿Çual es la diferencia entre la programación estructurada y la orientada a objetos?



2: ¿Cual es la sentencia que hace ejecutable a una clase en Java?


3: ¿Cuales son los tipos primitivos en Java?


4: ¿Que palabra nos permite abandonar inmediatamente un case de la sentencia switch?


5: ¿Que sentencia nos permite mostrar texto en pantalla?


6: Para poder ingresar datos mediante el teclado ¿que clase debemos importar?


7:¿Cuantas veces puede cambiarse el tamaño de un arreglo una vez dimensionado o inicializado?


8: ¿Un metodo puede sobrecargarse?(escribir otro metodo con el mismo nombre pero con diferentes parametros)


9: ¿Cual es el valor predeterminado de una variable String, int y boolean?


10:¿Se puede declarar un metodo dentro de otro?


completa la frase




1: La palabra clave ________ crea un nuevo objeto de la clase especificada a la derecha de la palabra clave.


2: La palabra clave _________ es un especificador de acceso.


3: La instruccion __________ se utiliza para ejecutar una accion si una condicion es verdadera y otra cuando es falsa.


4: La instrucción ____________ evalúa la continuación del ciclo ___________ de ejecutar cuerpo del ciclo; por lo tanto el cuerpo siempre se ejecutara al menos una vez


5: Un objeto de la clase __________ produce numeros aleatorios.


6: Un __________ nos permite crear conjunto de objetos que comparten un mismo tipo.


7: Si al principio de una instrucción while la condición es __________ el cuerpo nunca se ejecutara.


8: El operador _________ resulta true solo si ambas condiciones son verdaderas.


9: Un ___________ no lleva tipo de retorno, ni de dato, tampoco especificador de acceso.


10 La sentencia _________________ solo nos permite iterar en un arreglo y no modificar sus valores.




Descubre el Error


1: int valor1 = 2.2;





2: public static void(String[]){}




3: for(int i=0;i==10; i++)
  {
  suma = i+1;
  }



4: int metodoA()
{
 int b=10
    int metodoB()
   {
    b=45;
   }
}




5: String arregloA []= new arregloA[];



6: 
if(numero == 10);
{
System.out.println("numero es igual a 10");
}//fin del if




7: 
double arreglo2[] = new double[10];
arreglo2[10] = 12;










Arreglos y La sentencia for mejorada.




Los Arreglos son estructuras de datos que consisten en elementos relacionados por el tipo de dato. Los arreglos son estructuras de longitud fija, una vez inicializado su tamaño este se mantiene como  una constante, aunque se puede reasignar una variable tipo arreglo que haga refencia a un arreglo de longitud distinta.

Los arreglos son conjuntos de variables todas del mismo tipo, Es necesario recordar en que Java existen dos tipos de datos; los primitivos y los de tipo por referencia. Los arreglos son objetos, por ende, son del tipo por referencia, en realidad un arreglo es una referencia a un objeto arreglo en memoria (es por ello que se le considera como tipo referenciado).
Para la creación de un arreglo debemos especificar un tipo de dato, un nombre y un [ ](corchete abierto y cerrado)

Los objetos o valores dentro de un arreglo se ubican a partir de su "indice" o "subindice". el subindice de un arreglo siempre comienza en 0, por ende un arreglo de tamaño 5, sera asi.

c[ 5 ] = c[0]  ,  c[1]  , c[2]  ,  c[3]  ,  c[4]

Como el arreglo es de tamaño 5 y el subindice siempre comienza en 0, el ultimo subindice siempre sera 1 menos que el tamaño del arreglo. en este ejemplo el arreglo es de tamaño 5 el ultimo subindice es 4.

EJ:

int arreglo1[ ]; también puede ser int [ ] arreglo1;

estas sentencias lo único que hacen es crear un arreglo de valores int llamado arreglo1. pero no lo inicializa, esta declaración seria equivalente a declarar una variable como int num1;
Para inicializar el arreglo tenemos tres posibles caminos; simplemente declarar el arreglo como en el ejemplo, después dimencionarlo y por ultimo inicializarlo;

int arreglo1[ ];   //crea el arreglo
arreglo1 = new int[ 5 ];  //dimensiona el arreglo con un tamaño 5
arreglo1[ 0 ] = 33; //inicializa el subindice 0 con un valor de 33

Otra manera  es

int arreglo2[ ] = {22,102,1,5,99}; //crea en arreglo y lo dimensiona pasandole valores.
este arreglo es de tamaño 5,

¿que valor tendría en este arreglo  arreglo2[ 1 ]; ?

R; 102.  recuerda que el sub-indice de un arreglo siempre comienza en 0, en este caso [0]=22,[1]=102, etc...

También se pueden haber inicializado los valores de uno en uno a través de sus sub-indices el mismo ejemplo.


int arreglo2[] = new arreglo[5]; //crea el arreglo y le da un tamaño inmediatamente
arreglo2[ 0 ] = 22; //inicializa el indice con un valor del mismo tipo de dato del arreglo.
arreglo2[ 1 ] = 102;
etc,,,


Al crear un arreglo y dimensionarlo, pero no asignarle valores a sus subindices, java automáticamente inicializa el arreglo con los valores predeterminados dependiendo de su tipo... recordar, como ya puse en una entrada anterior: int, short, long, double, byte en 0, char en null, boolean en false y todos los de referencia en null.
*dimensionar un arreglo en la forma int c[4]; produce un error de sintaxis.

Ej:

//crea un arreglo de tamaño 10 y dale valores al azar entre 1 y 100


1     import java.util.Random;
2
3     public class arreglos
4     {
5        public static void main(String[]args)
6    {
7         int arreglo1[] = new int[10]; //crea y dimensiona un arreglo de tamaño 10  
8         Random azar = new Random();  //crea un nuevo objeto random
9         for(int i = 0; i<arreglo1.length; i++)
10      {
11         int num = azar.nextInt(99)+1;
12         arreglo1[i] = num;
13      }//fin del ciclo for
14  
15      for(int x=0; x<arreglo1.length; x++)
16       {
17         System.out.println("el valor del indice ["+x+"] es de :"+arreglo1[x]);
18        }
19    }//fin del metodo main
20    }//fin de la clase



En la linea 7  creamos y dimensionamos un arreglo de valores int cuyo tamaño es 10, en la linea 8 instanciamos (o creamos) un objeto de la clase Random que nos permite usar sus métodos y variables, en este ejemplo solo usamos el método nextInt(), que recibe un argumento de tipo entero el que establece el numero máximo de los posibles números, acá le pasamos como argumento 99 y esto es porque el numero cuenta desde el 0 hasta el que le pasemos, como acá es 99 podría ser un numero desde 0 (incluyéndolo) hasta 99, Como el ejercicio establecía que debían ser numero del 1 al 100 se le suma 1 (azar.nextInt(99)+1;). así aunque salga 0 seria 1 y si sale 99 serian 100 respectivamente   y le pasamos ese valor a la variable num.

en la linea 9 creamos un ciclo for, el que va a iterar mientras que i = 0 sea menor que arreglo1.length
El metodo .length es propio de los arreglos y su función es devolver el largo del arreglo, en este caso 10. es por eso que en el encabezado del for pongo que debe iterar hasta que sea menor que <arreglo1.length pues el i inicia en 0 (si dejaramos que iterara hasta que fuera menor o igual, en total daría 11 vueltas y nos daría un error Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: este es un arror por intentar llegar a un indice que noe sta en el arreglo, por ejemplo tenemos un arreglo de tamaño 10 e intentamos acceder al subindice 10, recordar que en un arreglod e tamaño 10 el ultimo subindice es 9 ). si el i iniciara en 1 entonces seria correcto poner <= .
en la linea 12 se realiza el "llenado del arreglo" ponemos arreglo1[ i ] para que vaya llenando el arreglo conforme itera el arreglo. así como en la primera vuelta i vale 0, se inicializa el subindice 0 del arreglo con algún valor al azar entregado por nexInt(99)+1
finalmente en la linea 15 crea otro ciclo for que iterara a traves del arreglo para mostrar sus valores.

La sentencia for mejorada

La instrucción for mejorada nos permite iterar a través de un arreglo o colección sin la necesidad de un contador, con lo que se evita la posibilidad de salir mas allá de los limites del arreglo.

su sintaxis es:

for(parametro : nombrearreglo)
{
instrucción
}

el parametro es una variable no inicializada del mismo tipo del arreglo, por ejemplo int. nombre arreglo es el nombre del arreglo sin los corchetes [ ]
//suma los elementos de un arreglo

int valores[ ] = {2,33,42,99,1};
int suma = 0;
for(int iterador : valores)
{
suma+=iterador;
}
System.out.println("El total de sumar los elementos del arreglo es : "+suma);

la variable iterador no se inicializa pues en este tipo de for realiza las veces de valor provisorio, por ejemplo en la primera vuelta, iterador toma el valor del elemento 0 del arreglo valores, así según este ejemplo en la primera vuelta iterador = 2, en la segunda iterador = 33 etc...

La sentencia for mejorada es util cuando debemos iterar sobre elementos de un arreglo pero no modificaros  tampoco se puede hacer referecia al iterador como se haria con uno en una sentencia for normal, ya que en este tipo de declaración el iterador no toma los valores 0, 1, 2... sino los valores de los elementos de arreglo, como recién dije..

Arreglos Multidimensionales


Los arreglos multidimensionales de dos dimensiones se utilizan con frecuencia para representar tablas de valores, las cuales consisten en información ordenada en fi las y columnas. Para identificar un elemento específico de una tabla, debemos especifi car dos subíndices. Por convención, el primero identifica la fi la del elemento y el segundo su columna. Los arreglos que requieren dos subíndices para identifi car un elemento específico se llaman arreglos bidimensionales (los arreglos multidimensionales pueden tener más de dos dimensiones). Java no soporta los arreglos multidimensionales directamente, pero permite al programador especificar arreglos unidimensionales, cuyos elementos sean también arreglos unidimensionales, con lo cual se obtiene el mismo efecto.
En general, a un arreglo con m fi las y n columnas se le llama arreglo de m por n.
Cada elemento en el arreglo a se identifica en la fi gura 7.16 mediante una expresión de acceso a un arreglo de la forma a [ fila ][ columna ]; a es el nombre del arreglo, fila y columna son los subíndices que identifi can
en forma única a cada elemento en el arreglo a por número de fila y columna.

imagen de "como programar en java". Deitel y Deitel




Arreglos de arreglos unidimensionales
Al igual que los arreglos unidimensionales, los arreglos multidimensionales pueden inicializarse mediante inicializadores
de arreglos en las declaraciones. Un arreglo bidimensional b con dos fi las y dos columnas podría declararse
e inicializarse con inicializadores de arreglos anidados, como se muestra a continuación:
int b[ ] [ ] = { { 1, 2 }, {3, 4} };
Los valores del inicializador se agrupan por fi la entre llaves. Así, 1 y 2 inicializan a b[ 0 ][ 0 ] y b[ 0 ][ 1 ],
respectivamente; 3 y 4 inicializan a b[ 1 ][ 0 ] y b[ 1 ][ 1 ], respectivamente. El compilador cuenta el número
de inicializadores de arreglos anidados (representados por conjuntos de llaves dentro de las llaves externas) en
la declaración del arreglo, para determinar el número de fi las en el arreglo b. El compilador cuenta los valores
inicializadores en el inicializador de arreglos anidado de una fi la, para determinar el número de columnas en esa
fi la. Como veremos en unos momentos, esto signifi ca que las fi las pueden tener distintas longitudes.
Los arreglos multidimensionales se mantienen como arreglos de arreglos unidimensionales. Por lo tanto, el
arreglo b en la declaración anterior está realmente compuesto de dos arreglos unidimensionales separados: uno que contiene los valores en la primera lista inicializadora anidada { 1, 2 } y uno que contiene los valores en la segunda lista inicializadora anidada { 3, 4 }. Así, el arreglo b en sí es un arreglo de dos elementos, cada uno de los cuales es un arreglo unidimensional de valores int.

Arreglos bidimensionales con filas de distintas longitudes
La forma en que se representan los arreglos multidimensionales los hace bastante flexibles. De hecho, las longitudes de las filas en el arreglo b no tienen que ser iguales. Por ejemplo,
int b[ ][ ] = { { 1, 2 }, { 3, 4, 5 } };
crea el arreglo entero b con dos elementos (los cuales se determinan según el número de inicializadores de arreglos anidados) que representan las fi las del arreglo bidimensional. Cada elemento de b es una referencia a un arreglo unidimensional de variables int. El arreglo int de la fi la 0 es un arreglo unidimensional con dos elementos (1 y 2), y el arreglo int de la fi la 1 es un arreglo unidimensional con tres elementos (3, 4 y 5).
Creación de arreglos bidimensionales mediante expresiones de creación de arreglos
Un arreglo multidimensional con el mismo número de columnas en cada fila puede crearse mediante una expresión de creación de arreglos. Por ejemplo, en las siguientes líneas se declara el arreglo b y se le asigna una referencia a un arreglo de tres por cuatro:
int b[ ][ ] = new int[ 3 ][ 4 ];

En este caso, utilizamos los valores literales 3 y 4 para especificar el número de filas y columnas, respectivamente, pero esto no es obligatorio. Los programas también pueden utilizar variables para especificar las dimensiones de los arreglos, ya que new crea arreglos en tiempo de ejecución, no en tiempo de compilación. Al igual que con los arreglos unidimensionales, los elementos de un arreglo multidimensional se inicializan cuando se crea el objeto arreglo.
Un arreglo multidimensional, en el que cada fila tiene un número distinto de columnas, puede crearse de la
siguiente manera:
int b[][] = new int[ 2 ][ ]; // crea 2 filas
b[ 0 ] = new int[ 5 ]; // crea 5 columnas para la fila 0
b[ 1 ] = new int[ 3 ]; // crea 3 columnas para la fila 1


ejemplo:


import java.util.Random;

public class arreglos
{
    public static void main(String[]args)
    {
    int arreglo1[][]={{3,44,55},{4,32,54}};
    for(int fila=0; fila<arreglo1.length;fila++)
    {
    for(int columna=0; columna<arreglo1[fila].length;columna++){
    System.out.printf("%d ",arreglo1[fila][columna]);
    }
        System.out.println("");
    }
    }//fin del metodo main
}//fin de la clase



Objetos, Métodos y Constructores.




"Comenzaremos con una analogía simple, para ayudarle a comprender el concepto de las clases y su contenido. Suponga que desea conducir un automóvil y, para hacer que aumente su velocidad, debe presionar el pedal del acelerador. ¿Qué debe ocurrir antes de que pueda hacer esto? Bueno, antes de poder conducir un automóvil, alguien tiene que diseñarlo. Por lo general, un automóvil empieza en forma de dibujos de ingeniería, similares a los planos de construcción que se utilizan para diseñar una casa. Estos dibujos de ingeniería incluyen el diseño del pedal del acelerador, para que el automóvil aumente su velocidad. El pedal “oculta” los complejos mecanismos que se encargan de que el automóvil aumente su velocidad, de igual forma que el pedal del freno “oculta” los mecanismos que disminuyen la velocidad del automóvil y por otro lado, el volante “oculta” los mecanismos que hacen que el automóvil de vuelta. Esto permite que las personas con poco o nada de conocimiento acerca de cómo funcionan los motores puedan conducir un automóvil con facilidad.
Desafortunadamente, no puede conducir los dibujos de ingeniería de un auto. Antes de poder conducir un
automóvil, éste debe construirse a partir de los dibujos de ingeniería que lo describen. Un automóvil completo tendrá un pedal acelerador verdadero para hacer que aumente su velocidad, pero aún así no es sufi ciente; el automóvil no acelerará por su propia cuenta, así que el conductor debe oprimir el pedal del acelerador.
Ahora utilizaremos nuestro ejemplo del automóvil para introducir los conceptos clave de programación de esta sección. Para realizar una tarea en una aplicación se requiere un método. El método describe los mecanismos que se encargan de realizar sus tareas; y oculta al usuario las tareas complejas que realiza, de la misma forma que el pedal del acelerador de un automóvil oculta al conductor los complejos mecanismos para hacer que el automóvil vaya más rápido. En Java, empezamos por crear una unidad de aplicación llamada clase para alojar a un método,
así como los dibujos de ingeniería de un automóvil alojan el diseño del pedal del acelerador. En una clase se proporcionan uno o más métodos, los cuales están diseñados para realizar las tareas de esa clase. Por ejemplo, una clase que representa a una cuenta bancaria podría contener un método para depositar dinero en una cuenta, otro para retirar dinero de una cuenta y un tercero para solicitar el saldo actual de la cuenta.
Así como no podemos conducir un dibujo de ingeniería de un automóvil, tampoco podemos “conducir” una clase. De la misma forma que alguien tiene que construir un automóvil a partir de sus dibujos de ingeniería para poder conducirlo, también debemos construir un objeto de una clase para poder hacer que un programa realice las tareas que la clase le describe cómo realizar. Ésta es una de las razones por las cuales Java se conoce como un lenguaje de programación orientado a objetos. Cuando usted conduce un automóvil, si oprime el pedal del acelerador se envía un mensaje al automóvil para que realice una tarea-hacer que el automóvil vaya más rápido. De manera similar, se envían mensajes a un objeto; cada mensaje se conoce como la llamada a un método, e indica a un método del objeto que realice su tarea.
Hasta ahora, hemos utilizado la analogía del automóvil para introducir las clases, los objetos y los métodos. Además de las capacidades con las que cuenta un automóvil, también tiene muchos atributos como su color, el número de puertas, la cantidad de gasolina en su tanque, su velocidad actual y el total de kilómetros recorridos (es decir, la lectura de su odómetro). Al igual que las capacidades del automóvil, estos atributos se representan como parte del diseño en sus diagramas de ingeniería. Cuando usted conduce un automóvil, estos atributos siempre están asociados con él. Cada uno mantiene sus propios atributos. Por ejemplo, cada conductor sabe cuánta gasolina tiene
en su propio tanque, pero no cuánta hay en los tanques de otros automóviles. De manera similar, un objeto tiene atributos que lleva consigo cuando se utiliza en un programa. Éstos se especifican como parte de la clase del objeto. Por ejemplo, un objeto tipo cuenta bancaria tiene un atributo llamado saldo, el cual representa la cantidad de dinero en la cuenta. Cada objeto tipo cuenta bancaria conoce el saldo en la cuenta que representa, pero no los saldos de las otras cuentas en el banco. Los atributos se especifican mediante las variables de instancia de la clase.
"Extracto de Como programar en Java, deitel y deitel, octava edición"


Metodos

Existen dos tipos de métodos; los que tienen valor de retorno y los de tipo void.

Los métodos con tipo de retorno devuelven un valor al ser llamados dentro de una clase, sintaxis

int suma(int num1, int num2)
{
int resultado = num1+num2;
return resultado;
}

Debemos poner un tipo de valor (en este caso int) antes del nombre del método. seguido del nombre del método van ( paréntesis ) en los cuales se pueden poner ( o no ) argumentos los cuales vana ser manipulados al interior del mismo. Los tipos de valores de los argumentos deben ser exactamente iguales a los de la declaración del método. *en realidad y siendo extricto los tipos de datos d elos argumentos si se pueden mezclar pero recuerden que el retorno es uno solo
la sentencia final del método con tipo de valor de retorno es " return " que es la encargada de retornar un valor del mismo tipo de la declaración del tipo de método.

métodos sin tipo de retorno. Tambien podemos crear métodos sin tipo de retorno, estos son los void, al igual que el otro tipo, estos pueden o no llevar argumentos y al no devolver un valor simplemente se ejecutan las acciones del cuerpo.

void miMetodo()
{
System.out.println("llamaste a este método");


Al llamar al método  " miMetodo() " el resultado seria simplemente el mensaje especificado en su cuerpo
un metodo void con argumentos.

void miMetodo(String  nombre, String apellido)
{
System.out.println("Bienvenido a la programación Don :"+nombre +" "+apellido);
}

Lo cual devolvería:   Bienvenido a la programación Don -------  --------
*siendo estricto todos los métodos tienen valor de retorno, ya que void también es un tipo de retorno.

Cuando cambiamos los valores de variables de instancia (son las declaradas afuera de cualquier método  incluyendo el o main). en un método, estos nuevos valores solo se mantienen validos al interior del método a menos que sea una variable de tipo static.
*las variables declaradas como static (static int numero;) cambian sus valores reales desde cualquier lugar de una clase


EJ:


class EjemploMetodos
{
    //metodo con tipo de valor de retorno y argumentos
    int suma(int num, int num2)
    {
    int suma = num+num2;
    return suma;
    }
    //metodo con tipo de retorno void
    void mensaje(int num, int num2)
    {
    System.out.println("El valor de la suma es :"+(num+num2));
    }
 
    public static void main(String[]argumentos)
    {
    EjemploMetodos ini = new EjemploMetodos();
 
    System.out.println("La suma es :"+ini.suma(44, 12));
    ini.mensaje(10,15);//lamamos directamente al metodo void
 
    }//fin del main
}//fin de la clase



En el main, instanciamos la nuestra propia clase para poder llamar a los metodos desde su interior, ya que el método main al ser static solo permite llamar a otros metodos estáticos (static)  con la instanciacion eliminamos este problema.
llamamos al método suma a traves de la variable ini que creamos.  "ini.suma( )" y le pasamos dos argumentos de tipo int. el método realiza su tarea y devuelve un valor int que es la suma de los dos especificados.

*Es un error en tiempo de compilación especificar valores de otros tipos de datos a los solicitados por el método llamado.

*El método  println no permite poner en su interior métodos con valor de retorno void.

*Los metidos con tipo de valor de retorno, si no son usados en un mensaje deben pasarse como valor a otra variable ya que de lo contrario el retorno (un valor) queda sin contenedor.

*Es necesario que te familiarices con la vasta coleccion de clases de la api de Java, asi que evita inventarlo todo de nuevo, hay cerca de 6000 clases disponibles. http://docs.oracle.com/javase/6/docs/api/
*todas las clases  extienden de manera predeterminada del paquete java.lang que es el paquete padre de todo programa en java, es por eso que se pueden utilizar clases como String, Math, System... sin necesidad de importarlas.
*no se puede declarar un metodo dentro de otro.



Constructores 

Un constructor es una clase especial de método del cual podríamos diferenciarlos por:

1. Un constructor debe tener el mismo nombre de la clase en que se declara.

2. El constructor no tiene tipo de valor de retorno.

3. Los constructor no usa la sentencia return.


La labor del constructor es poner a los objetos de la clase en un estado consistente, es decir, el constructor inicializa las variables de clase y las pone en un estado correcto para ser utilizadas,
Cuando tenemos variables de clase y estas no han sido inicializadas con valores se produce un error en tiempo de ejecución, es por ello que el constructor se encarga de dicha tarea.
De manera predeterminada las variable de tipo primitivo se inicializan en 0, a excepcion de las booleanas que se establecen en false y las de tipo de referencia (cono un String) en null.

Los constructor se ejecutan de manera predeterminada cuando instanciamos una clase atraves de la palabra clave new. en caso de no especificar un constructor, el compilador establece un constructor sin argumentos para inicializar las variables y poder poner al programa de manera consistente en la memoria.

Java nos permite tener mas de un constructor por clase a través de la denominada "sobrecarga de constructores. Esto es diferenciar a los diferentes constructores solo por el numero y tipo de sus argumentos.
ej:

class Sobrecarga
{
 Sobrecarga(){
}//fin del constructor 1

Sobrecarga(int valor1){
}//fin del constructor 2

Sobrecarga(String nombre, int valor1){
}//fin del constructor 3

}//fin de la clase

Al instanciar nuestra clase Sobrecarga, podemos hacer la diferencia entre que constructor necesitamos utilizar dependiendo del numero de argumentos que le pasemos.

por ejemplo para ocupar el constructor 3:

Sobrecarga instancia = new Sobrecarga ("Pedro Gonzales",14); //el numero y orden de los argumentos
                                                                                                   debe ser el mismo que en la declaración
                                                                                                   del constructor.


Tambien es posible hacer que los diferentes constructores de una clase se comuniquen entre si, atraves de la palabra clave this.
la palabra clave this nos permite llamar a un constructor dentro de otro. ejemplo.



class Generalidades
{
    int numeroi;
    int numeroe;    //estas dos variables no las inicialize para que lo hagan los constructor
 
    Generalidades(int i, int e)          /*constructor de dos variables.
    {
    numeroi = i;                             * le damos los valores de los argumentos  i y e a las variables de instancia,                    
    numeroe = e;                           */inicializandolas.
    }
 
    Generalidades(int x)            /*segundo constructor con un solo argumento, este constructor
   {                                           *utiliza this para llamar al contructor de dos argumentos
    this(x, 0);                             *y le pasa el valor de X como primer argumento y establece el segundo
   }                                         */en un valor cualquiera
 
    void imprimir()
    {
        System.out.printf("valor de numeroi : %d\nvalor de numeroe : %d\n",numeroi, numeroe);
    }
 
    public static void main(String[]agrs)
    {
        Generalidades ini = new Generalidades(55);  /*llamamos al constructor de un solo argumento
        ini.imprimir();                                                *y le damos un solo valor, este lo establecen en su
                                                                            *En su variable X y se lo pasa atraves de this al
    }//fin del metodo main                                       * constructor de dos argumentos.
}// Fin de la clase




la salida de este programa es la sgte:


valor de numeroi : 55
valor de numeroe : 0
GENERACIÓN CORRECTA (total time: 0 seconds)

Como pueden comprobar a pesar de que llamamos en la instanciacion al contructor  de un argumento, en realidad llamamos al de dos.


Especificadores de Acceso


Un especificador (modificador) de acceso o alcance es una palabra clave (reservada) que nos permite controlar nivel de alcance que tiene cada variable, método o clase. Existen tres public, protected,  private, static, final. 

public establece un nivel de acceso total, es decir  una clase public puede ser usada por otras clases del mismo paquete y de otros paquetes no relacionados, lo mismo para los métodos y variables.
public es el especificador de acceso mas utilizado en estudiantes ya que no nos enfrentamos a la dificultad (¿..?) de tener que determinar que se puede y que no se puede utilizar en un clase.

private establece un nivel restringido de acceso, En el cual los miembros declarados como tal solo son accesibles dentro de la clase, aunque la clase herede de esta ultima. las variable y métodos private son usados cuando los clientes de una clase no deben preocuparse (ni les debe importar) como se efectúan las acciones claves de un programa. establecer miembros private establece el mayor nivel de seguridad.

protected establece un nivel de acceso intermedio entre public y private en el que los miembros solo son accesibles por clases y métodos dentro del mismo paquete.

static el modificador static crea variables y metodos de clase (a esto es lo que nos referimos cuando hablamos de variables de clase) estos objetos pueden ser llamados desde cualquier parte de la clase modificando sus valores reales de forma definitiva. la diferencia con una variable normal es que cuando llamamos a una variable de instancia (normal) cambiamos su valor solo en ese instancia (metodos, etc..) en cambia una variable estatica cambia de valor definitivamente cada vez que se llama, en palabras simples actualizamos su valor real desde cualquier parte del programa.


final el modificador final, crea una constante, en realidad en java no existen las constantes, pero final hace que las variables imiten su comportamiento. Cualquier intento por modificar una variable final creara un error en tiempo de ejecucion.
Un ejemplo de final, es la variable PI, de la clase Math


class Generalidades
{
  public static void main(String[]agrs)
    {
        System.out.println("El valor de  Pi es"+ Math.PI);
        System.out.println("nuevo valor de Pi"+(Math.PI = 5));//intentamos cambiar el valor de PI

    }//fin del metodo main
}// Fin de la clase

Esta seria la salida del compilador.:


El valor de  Pi es3.141592653589793
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - cannot assign a value to final variable PI
at Ejemplo.Generalidades.main(Generalidades.java:12)


lo que esta en rojo es la descripción del error cannot assign a value to final variable PI (no se puede asignar un valor a la variable final PI)


conforme avance el curso iremos agregando mas datos sobre los modificadores y especificadores.

Resumen 1


-Una clase comienza con la palabra reservada class y su cuerpo esta delimitado por { }.

-Por convención la primera letra del nombre de una clase comienza con mayuscula y la primera letra de cada palabra después de la primera también. ej: class SumaDeEnteros { }.

-Java es un lenguaje KeySensitive, es decir; es sensible a las mayúsculas y minúsculas, no es lo mismo MiMetodo, que miMetodo.

-Cada instrucción en java finaliza con un ; (no es lo mismo una instrucción que una linea de código)

-En java existen dos tipos de datos, Los primitivos y los de referencia:
Los primitivos son: byte, boolean, int, short, long, double, float, char.
Los referenciados: son cualquiera que no sea primitivo (clases, metodos, etc...)

-En lineas generales existen dos formas de inicializar una variable:
int variable = 10;  //de esta manera  la inicializamos de inmediato con un valor determinado.
int variable;  //de esta otra manera, primero la creamos y despues le damos un valor
variable = 10;
*Es un error en tiempo de ejecución intentar utilizar una variable sin antes haberla inicializado.

-Es un error lógico intentar utilizar una variable antes de inicializarla con un valor.

-System.out se conoce como el objeto de salida estándar  esta permite a las aplicaciones java mostrar informacion atraves de la consola del IDE o del MSDOS si estamos compilando las clases sin IDE.

-System.out puede usarse con tres métodos para imprimir en pantalla. print, printf y println.

-Existen los denominados caracteres de escape que nos permiten mejorar y simplificar las cadenas de caracteres, entre ellos  \n , \\ , \r , \t , \"

-Un especificador de formato nos permite "modelar" las cadenas de caracteres a través de printf. el primer argumento de printf ( ), es una cadena de formato que puede consistir en texto fijo y especificadores de formato. El método printf imprime el texto fijo de igual forma que print o println. Cada especificador de formato es un receptáculo para un valor, y especifica el tipo de datos a imprimir. Los especificadores de formato también pueden incluir información de formato opcional.
Los especificadores de formato empiezan con un signo porcentual (%) y van seguidos de un carácter que
representa el tipo de datos. Por ejemplo, el especificador de formato %s es un receptáculo para una cadena.

-Para utilizar alguna de las clases pre diseñadas de java,debemos especificarla mediante su ruta y una declaración import.

-a través del import java.util.Scanner; podemos utilizar esta clase para ingresar datos desde el teclado para luego mostrarlos en pantalla (si queremos).

- una instanciacion de clase nos sirve para utilizar todos los miembros de esa clase ej:
Scanner intro = new Scanner();
la palabra intro es opcional (su nombre) ya que es mediante la cual llamaremos a los componentes de Scanner, la palabra clave new  es reservada de java y se utiliza para crear un nuevo objeto.

*Es un error de sintaxis declarar una clase del paquete predeterminado de java con la primera letra minuscula, por ejemplo ; scanner    ---> Scanner

- La sentencia condicional if nos permite ejecutar acciones siempre y cuando se cumpla una condición. su sintaxis es :

if(condición)
{
acciones                            
}

*notar que el cuerpo de un if va delimitado por { } inmediatamente después de los paréntesis de la condición.

*Es un error de sintaxis escribir un punto y coma después de los paréntesis de la condición del if o al finalizar su cuerpo  }

La sentencia compuesta if - else nos permite ejecutar acciones en caso que la condición del if no se cumpla:
if (condición)
{cciones si las condiciones del if no se cumplen
   acciones
}else
{
   acciones a realizar si la condición del if no se cumple
}

*Es un error de sintaxis no especificar { } para el cuerpo de la sentencia else.

Existe una tercera forma de usar de usar el condicional if, es a través de:     if-else if-else

if ( condición 1)
{
  //acciones si se cumple la condición 1
}else if ( condición 2)
{
  //acciones si se cumple la condición 2
}else
{
 //acciones si no se cumple ninguna condición
}

*el numero de else if puede ser cualquiera, va a depender solo del numero de condiciones que quieras usar
*la sentencia fina else, es opcional, pero se suele usar en el caso de que no se cumpla ninguna condiciones de los if asegurarnos de que se ejecute algo.

-Switch es otra sentencia de selección múltiple o condicional (En diversos libros aparece con muchos nombres) al igual que if switch nos permite agregar múltiples opciones si se cumplen ciertas condiciones. sin embargo switch tiene una particularidad : evalúa solo valores primitivos y en algunos casos muy especiales objetos (como serian las clases de envoltura de tipos, que veremos mas adelante).

Switch (valor a comparar)
{
case 1:
{}
break;
case 2:
{}
break;
case 3:
{}
break;
case etc...
{}
break;
default
{}
}//fin del switch


El valor o variable que encerramos entre los ( ) de la cabecera de switch es el valor que vamos a comparar con los case. el primer case dice 1, es decir si el valor de la cabecera vale 1 ejecutara ese case entrando así en el cuerpo delimitado por las llaves {}
la sentencia break; hace el trabajo de sacarnos del switch en caso de que ese case se cumpla. de lo contrario el compilador continuara leyendo el código hasta el final de switch y ejecutando las acciones dentro de los demás case.
la sentencia final default nos permite tomar alguna acción si es que no se cumple ningún default.

El ciclo for nos permite iterar un numero determinado de veces ejecutando acciones especificas. sintaxis:

for(int i=0; i<5; i++)
{
Systemout.println("El valor de  i en la vuelta "+( i+1)+" es :" +i);
}

esto daria la salida


El valor de  i en la vuelta 1 es :0
El valor de  i en la vuelta 2 es :1
El valor de  i en la vuelta 3 es :2
El valor de  i en la vuelta 4 es :3
El valor de  i en la vuelta 5 es :4


en el encabezado del for delimitado por ( ) debemos colocar tres indicadores
1: la variable que hará las veces de contador, se puede declarar e inicializar acá mismo como con el ejemplo o si se declara e inicializado afuera solo haría falta nombrarla, pero debe ponerse. el segundo termino es la condición es decir-el ciclo se repetirá mientras esto se cumpla-  en el ejemplo el ciclo se repetirá hasta que i sea menor que 5 osea hasta que i = 4, sin embargo el ciclo igual da 5 vueltas pues el i se inicializo en 0.
el tercer termino es un incrementador, en este caso incrementa a i en 1 cada vez que da una vuelta.
cuando i termina de dar la 5 vuelta su valor es 4, se devuelve a la cabecera del for incrementado en 1, osea i esta en 5 y revisa la condición del for, como i ya no es menor que 5 se sale automáticamente sin imprimir su nuevo.