lunes, 30 de junio de 2014

MODULO 9: Colecciones
Una colección es la representación de un objeto que administra o maneja un conjunto de objetos conocidos como elementos.

Las colecciones representan estructuras de datos con cierta implementación (Arboles, Pilas, Listas, Colas).

Los arreglos son estáticos.

asList

public static <T> List<T> asList(T... a)
Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.) This method acts as bridge between array-based and collection-based APIs, in combination withCollection.toArray(). The returned list is serializable and implements RandomAccess.This method also provides a convenient way to create a fixed-size list initialized to contain several elements:
     List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
Parameters:
a - the array by which the list will be backed
Returns:
a list view of the specified array
Cuando se convierte un arrays (que son estático) a una lista, ya no se pueden agregar más puesto que son estáticos
public class TestArrays {
 
    public static void main(String[] args) {
        String [] sa = {"Rojo", "Naranja", "Verde", "Blanco", "Azul"};
     
        List sl = Arrays.asList(sa);
        sa[0]="Amarillo";
        sl.add("Rosa");   // Error porque los array son estáticos aun cuando las listas no lo son.
        for (String s : sa) {
            System.out.println(" "+s);
        }
        System.out.println("sa= "+sa);
        System.out.println("sl = "+sl);
     
    }
 
}


Arrays.sort(sa);
        int a = Arrays.binarySearch(sa, "Aaa");

La búsqueda binaria regresa la posición en donde se encuentra siempre y cuando se encuentre (Se recomienda que este ordenado para un mejor funcionamiento) en caso de que no lo encuentre nos trae el valor de la posición donde debería estar -1.

Colecciones
al.set(0, "Robben");
al.add(0, "Marquez");

set: Set reemplaza lo que hay en esa determinada posición.
add: inserta en la posición específica y recorre lo que hay ahí.

List al = new ArrayList();
       
        al.add(0, "Marquez");
        al.set(0, "Robben");
        al.add(0, "Marquez");
        
        System.out.println(""+al);

--- Output ---
[Marquez, Robben]


Si ponemos primero set en el primer add marcaría error porque el set reemplaza y si esta vacío, no hay nada que reemplzar.

Listas doblemente Ligada
peeak - regresa el primier elemento pero no lo elimina.
poll: - regresa el primer elemento y lo elimina.

Ejemplo de uso
public class TestLLL {
    public static void main(String[] args) {
        LinkedList ll = new LinkedList();
        ll.add("Manzana");
        ll.add("Mango");
        ll.add("Uva");
        ll.add("Fresa");
        ll.add("Pera");
        ll.add("Uva");
        System.out.println(""+ll);
        ll.peek();
        ll.poll();
        
        System.out.println("" + ll.poll());
        System.out.println(""+ll);
    }  
}

-- Output --
[Manzana, Mango, Uva, Fresa, Pera, Uva]
Mango
[Uva, Fresa, Pera, Uva]

Clase set
public class TestHS {
    public static void main(String[] args) {
        Set hs = new HashSet();
        
        hs.add(15);
        hs.add(2);
        hs.add(3);
        hs.add(3); //No permite repetidos pero si compila, pero al mostrarlo no lo muestra
        hs.add(78);
        hs.add(1);
        
        System.out.println(""+hs); //No los ordena 
        
    }
}

Este método utiliza el método equals.

TreeSet
Son ordenados, no duplicados.


Colas con prioridad
Es como un árbol que va buscando el balance, en caso de que el hijo sea menor que el padre, el padre le deja el lugar al hijo y el padre toma el lugar que el hijo.

Empieza de izquierda a derecha.
si tenemos 5, 8 ,23, 2, 8
El árbol sería de la siguiente forma

                   2
                   ^
             5       23
             ^
          8     8


Ejemplo
package EjCPQ;

import java.util.PriorityQueue;

public class EjPQ {
    public static void main(String[] args) {
        PriorityQueue pq = new PriorityQueue();
        pq.add(5);
        pq.add(8);
        pq.add(23);
        pq.add(2);
        pq.add(8);
        pq.add(8);
        pq.poll(); //Elimina el elemento padre, en este caso luego de la eliminación se recorren los elementos
        pq.peek(); //Sól muestra el valor del padre principal.
        pq.poll();
       
        System.out.println(""+pq);
    }
}

-- output --
[8, 8, 8, 23]

Interfaz MAP
Similares a las colecciones (es una colección pero no extiende de colecctions) pero permiten tener clave, valor, la clave es única. Sirven como diccionarios.
LOS MAPAS NO EXTIENDEN DE COLECCIONES POR LO TANTO NO TIENEN EL MÉTODO ADD

NO ORDENA, sin embargo casi salen ordenados porque los acomoda de tal forma que los va comparando para no aceptar claves repetidas.

Pero tiene otros métodos:
  - put(k,v):  Sirve como el add en las colecciones, se ingresa la clave + valor, las llaves no son repetidas            pero los valores pueden ser repetidos.
  - 

Ejemplos de la interfaz map<k,q>

package EjIM;

import java.util.HashMap;
import java.util.Set;
import java.util.TreeSet;

public class TestM {
    public static void main(String[] args) {
        HashMap ma = new HashMap();
        ma.put("uno", 12);
        ma.put("cinco", 54);
        ma.put("tres", 23);
        ma.put("uno", 84); //esta clave esta duplicada, pero este valor (84) actualiza al 12 que ya estaba
                                    // porque no acepta claves duplicados, solo actualiza
        ma.put(null, 12);   //en algunas implementaciones acepta llaves NULAS        


        Set s =  ma.keySet(); //el método keySet() regresa el conjunto de llaves dentro del mapa
                                         // y como regresa un set pues por eso el s de tipo Set.
Collection tv =  ma.values(); //obtenemos los valores
        
        System.out.println(""+ma); 
        System.out.println(""+s);
        System.out.println(""+tv);

//#        

    }
}
-- output --
ma_ {null=12, tres=23, cinco=54, uno=84}
s_ [null, tres, cinco, uno]
tv_ [12, 23, 54, 84]

TreeMap
La diferencia con treeSet es la forma en como compara y ordena los numeros, los treeSet NO ordena los numeros y permite arboles balanceados, en el caso de los treeMap si ordena las claves. 

Ejemplo:

Si en //# agregamos los siguientes

TreeMap tm = new TreeMap();
        //Los treeMap es parecido al treeSet
        tm.put(1, "ferrari");
       // tm.put(null, "bocho"); //Error. Los arboles no permiten claves nulas
        tm.put(45, "nissan");
        tm.put(2, "ford");
        tm.put(6, "mercedez");
        tm.put(14, "combi");
        
        System.out.println("tm_ "+tm);

-- output --
ma_ {null=12, tres=23, cinco=54, uno=84}
s_ [null, tres, cinco, uno]
tv_ [12, 23, 54, 84]
tm_ {1=ferrari, 2=ford, 6=combi, 45=nissan}  //Se puede ver que estar ordenados por clave

Comparable vs Comparator




Genericos
habilidad de crear una clase donde el usuario final puede decidir de que tipo de dato quiere trabajar.

Así se define una clase generica, donde el usuario decide que tipo de dato.
package Genericos;
public class MiGenerica<T> {
    
}

También se puede hacer lo siguiente
public class MiGenerica<T,E> {} //Se definen dos tipos de datos.

... continuando con el ejemplo

package Genericos;


public class MiGenerica<T> {
    private T variable;
    public T m(T j){
        return j;
    }
}

package Genericos;

import java.util.ArrayList;
import java.util.List;


public class TestGen {
    public static void main(String[] args) {
        MiGenerica<String> mg = new MiGenerica<String>();
        
        List<Integer> l = new ArrayList<Integer>();
        l.add(34);
        
    }
   
}

En Genéricos vienen los conceptos 
      Invarianza
      Covarianza
      Contravarianza 


Estudiar Para los Simuladores
método hasCode
interfaces y clases con metodos largos (asfnsk{ sd fs};)
para que sirve el write de archivos
DateFormat (dayFormat existe ?, getDay ?)
No puede iniciar dos hilos vivos t.star(); t.start(); //error en tiempo de ejecución
si se pone un ; solo es correcto









viernes, 27 de junio de 2014

MODULO 8: Excepciones
Porque todos comentemos errores, existen las excepciones :-)

Definir Excepciones, Usar try, catch, and finally
                                                        --------
                                                       | Object |
                                                       ---------
                                                             ^
                                                 ->         |                 <¬
                                           Error                           Exception



Los errores se pueden personalizar por las diferentes que ofrece java pero siempre van de lo especifico a lo general

public class TestA {
    static Integer i;
    public static void main(String[] args) {
        A a = new A();
        try{
        a.cociente(100, i);
        }catch(ArithmeticException ae){ //mas especifico
            System.err.println("No puedes dividir por cero");
        }catch(NullPointerException npe){
            System.out.println("Variable null");
        }catch(Exception e){ //más general
         
        }
    }
}

Los errores no son tratados en el try{}catch(Exception e){}

public class TestA {
    static Integer i=5;
    public static void main(String[] args) {
        A a = new A();
        try{
        throw new ClassFormatError(); //Esto no es atrapado por ninguno porque no es exception es un                                                                   // ERROR.
     
        }catch(ArithmeticException ae){
            System.err.println("No puedes dividir por cero");
        }catch(NullPointerException npe){
            System.out.println("Variable null");
        }catch(Exception e){
            System.out.println("Error no identificado ");
        }
    }
}

Por lo tanto lanza un error.
Las exception NO son atrapados pero si se pone Error como lo siguiente
public class TestA {
    static Integer i=5;
    public static void main(String[] args) {
        A a = new A();
        try{
        a.cociente(100, i);
        throw new ClassFormatError();
     
        }catch(ArithmeticException ae){
            System.err.println("No puedes dividir por cero");
        }catch(NullPointerException npe){
            System.out.println("Variable null");
        }catch(Error e){ //                                               Error
            System.out.println("Error no identificado ");
        }
    }
}


Cuando nadie se hace responsable de una Eception al final la maquina virtual de java (JVM)  se hace responsable y lo único que hace es matar todo.

finally
El finally siempre se ejecuta y va con:
try{
}finally{

}

o bien
try{ }catch(Exception e){}finally{}




Describir categorias de excepciones
 - Excepciones lanzadas por la máquina virtual
 - Excepciones de programación

Para la certificación es importante aprenderse una tabla de 12 excepciones y quien las lanza si la máquina virtual o el programador


Otra forma de lanzar Excepciones
es a travez del throws es decir sólo lanza pero no se hace responsable.


package EjCTC;

public class A {
 public void cociente(int a, int b)throws ArithmeticException{
     System.out.println(" "+a+"/"+b+" = "+a/b );
 }  


}
Con lo anterior aun truena en donde se llamo, solo se le dice que es un código peligroso

Ahora bien si hacemos lo siguiente:
import java.io.IOException;

public class A {
 public void cociente(int a, int b)throws IOException {               //Linea 3
     throw new IOException();                                                   // Linea 5
     //System.out.println(" "+a+"/"+b+" = "+a/b );
 }  


}

Si la linea 3 no se pone pero si la linea 5 marca error porque tu estas enviando algo identificado por lo tanto o TE RESPONSABILIZAS (try catch) o la LANZAS (throws)

Con lo anterior no quiere decir que ya no truene ya que debemos tener cuidado en donde lo llamamos que es ahí donde dará problemas puesto que ahí llega la excepcion identificada y lanzada. Ahí es donde podemos atraparla con un try y un catch.

Si en el padre estas lanzando una Excepcion en el método hijo tienes que sobrescribirla 

Si queremos crear nuestras exception, sólo hay que extender (Extends Exception) de la clase Exception, pero tu tienes que definir los mensajes.

Aserciones
Sirven para depurar código, se pueden habilitar o deshabilitar. Verificamos cierto valor. Nos sirve como desarrolladores, una vez terminada la aplicación la puedes quitar.
Es una especie de un if.

Es una expresión boleana, en caso de que se verdadera la condición se va a ejecutar normalmente, pero si el resultado es false, entonces produce un ERROR. Entonces vas al código y lo corriges.


Usos inapropiados (si funcionan, pero no debería usarse para eso) -> Pregunta de examen
Métodos públicos

Las aserciones por default esta deshabilitadas para no consumir recursos, esa es la diferencia entre una aserción y un if. Las aserciones aunque esten estan deshabilitadas.

¿Cómo se hablitan?
Se configura en las propiedades del proyecto y en la forma VM Option: -ea

Por consola:
javac nomArchivo.java
java -ea nomArchivo

Las assert te mandan el error pero no corrigen el problema, es solo que te avisa.

USO:
public class A {
 public void cociente(int a, int b) {
   
     assert(a>0):"a no es mayor a 0";  
   
     System.out.println(" "+a+"/"+b+" = "+a/b );
 }  
   


}








jueves, 26 de junio de 2014

MODULO 7

  • Crear inicializadores, varibles y métodos estáticos.
La palabra static
Cuando se usa static, no pertenece al objeto si no a la clase

No pertenece al objeto, sino a la clase.
Puede ser compartida con todas las clases (la misma para todas).

Para acceder a un miembro static, se necesita el nombre de la clase+ punto + el miembro. Ej: clase.varStatic


Las variables static pueden ser accedidos desde un objeto de clase o desde una clase.
Clase c = new Clase();
c.varStatic;


Ejemplo de una variable static



package marciano;

public class Marciano{ 

    public static int cuentaMarciano=5; 

}

package marciano;
public class Rambo{ 
    public void mataMarciano(){ 
        if(Marciano.cuentaMarciano>0){
        Marciano.cuentaMarciano-=1;
        System.out.println("Un marciano ha muerto por Rambo, quedan "+ Marciano.cuentaMarciano+" vivos"); 
        }else{
        System.out.println("Rambo: todos los marcianos han muerto :(");
        } 
    } 


package marciano;
public class Santo{ 
    public void mataMarciano(){ 
        if(Marciano.cuentaMarciano>0){
        Marciano.cuentaMarciano-=1; 
        System.out.println("Un marciano ha muerto en manos de Santo, aun viven "+Marciano.cuentaMarciano +" marcianos");
        }else{
        System.out.println("Santo: todos los marcianos han muerto :(");
        }             
    } 
}


package marciano;
public class App{
public static void main(String args[]){
            
            Rambo r = new Rambo();
            Santo s = new Santo();
            r.mataMarciano();
            s.mataMarciano();
            
            System.out.println("queda: "+Marciano.cuentaMarciano);
}
}

Si ejecutamos App mostrará: -----
Un marciano ha muerto por Rambo, quedan 4 vivos
Un marciano ha muerto en manos de Santo, aun viven 3 marcianos
queda: 3


En caso de no ser static cuando Rambo entre ha matar un marciano será diferente a cuando Santo mate uno, es decir serian una variable para cada uno, no compartida.


Métodos estáticos
Los métodos estáticos de un padre, si es sobrescrito en un hijo debe conservar el modificador.


Reglas de los Métodos static:
Una método de tipo static es un método de clase y se accede clase.metodoStatic(); o bien con un objeto de clase en algunos casos.

También un método static puede ser accedido cuando se importa el paquete en el que esta usando importando el contexto estatico Ej. import static ua.pa.A.mFinal; donde mFinal es un métod static.
    - No es correcto dejarlo así import static ua.pa.A; o así import static ua.pa.*; Pero si es correcto así  import            static ua.pa.A.*;

    - El orden es import static NUNCA es static import

Los métodos static al igual que los atributos static NO se son alcanzados por el super. 

Pueden sobrescribirse pero deben conservar el modificador static, si no marca error. Es decir no se sobrescribe como tal pero si lo usas debes a fuerza ponerle el modificador static y respetar la regla de los modificadores de igual o menor nivel de acceso.

Cuando se tiene un objeto de tipo A y A es la clase padre y tiene el metodo static cuando hacemos A a = new B();, lo anterior suponiendo que B hereda de A y B tiene el método cuando hagamos a.metodoStatic(); nos traerá el del padre y no el del hijo.


-------------------------------
Recodar que cuando se hereda un método el tipo de retorno es el mismo cuando son casos finales o primitivas
String, Interger o primitivas
Si son clases de usuario en el de abajo si pueden ser de otro tipo de retorno y sobrescribirlos.


inicializadores static

class A{
static{

}

}

El inicializador tiene la característica que se carga sin que se invoque a la clase, es decir se carga primero.

Desde un CONTEXTO ESTÁTICO no puedes acceder a cosas no ESTÁTICOS, es decir no se pueden inicializar variables que NO SEAN STATIC

  • Crear variables, métodos y clases final.
La palabra final
Una clase que es final no puede tener hijos, es decir no es heredable o extendida.
Los métodos si los marcar finales no se pueden sobrescribir. Garantiza que ese método ya no sea modificado.



final int a; 
Esta variable es definida como constante y esta inicializada con 0.

tipos de constantes
- Si no se inicializan al momento de declararla, se debe inicializar en el constructor o La inicializas cuando la declaras.

final int a = 5; //o en el contructor

- constante compartida, pero se inicializa al momento de declararla
static final int a  = 5;

*Pero también puede crear un inicializador static y ahí definirla, ¿Cómo?
static int a;
static{

a = 5;
}

Porque el inicializador tiene la característica que se carga sin que se invoque a la clase, es decir se carga primero.

recordar:
Desde un CONTEXTO ESTÁTICO no puedes acceder a cosas no ESTÁTICOS, es decir no se pueden inicializar variables que NO SEAN STATIC.



  • Crear y utilizar tipos enumerados.
un enumerado es un conjunto finito de valores.
NO ES UNA CLASE
NO ES UN INTERFAZ

Es un ENUM

El ENUM se puede crear dentro de una clase y para tener acceso cambia a si se declara por separado.

Los enum NO SE PUEDEN;
- Hacer comparaciones.
- Operaciones Aritméticas.

si sólo agregas los valores NO necesita ; a menos que agregues algo más en el enum 

----------

package EjE;





public enum Palo {
    PICAS, CORAZONES, DIAMANTES, TREBOL
    
}

----------

si agregas algo, entonces;


package EjE;





public enum Palo {
    PICAS, CORAZONES, DIAMANTES, TREBOL;
    
    private final String nombre = "Samuel";
    
}

Los enumerados pueden tener:
Atributos
Métodos 
Constructores

El constructor sólo va a servir para inicializar los valores de tu descripción así es que debiera ser private.

Ejemplo de Enums




package EjE;




public enum Palo {
    PICAS("Picas"), CORAZONES("Corazones"), DIAMANTES("Diamantes"), TREBOL("Trebol");
    
    private final String nombre;
    
    private Palo(String n){
        this.nombre = n;
    }
    
//    como nuestra varibale es una constante que de asigna un valor en el constructor
//    debenos crear el siguiente método.
    public String getNombre(){
        return nombre;
    }
  
    
}


package EjE;

public class NaipeBaraja {

  private Palo palo;
 private int rango;
    
  

  public NaipeBaraja(Palo palo, int rango) {
    this.palo = palo;
    this.rango = rango;
  }
  
  public Palo getPalo(){
      return palo;
  }
  
  public int getRango(){
  return rango;
  }
  
}


package EjE;

public class TestNaipeBaraja {
  public static void main(String[] args) {

    NaipeBaraja naipe1 = new NaipeBaraja(Palo.CORAZONES, 2);
    System.out.println("el naipe1 es: " + naipe1.getRango() + " de " + naipe1.getPalo().getNombre());

    //Puede crear un naipe de un palo inventado.
    NaipeBaraja naipe2 = new NaipeBaraja(Palo.DIAMANTES, 2);
    System.out.println("el naipe1 es: " + naipe2.getRango()+ " de " + naipe2.getPalo());
                                                                                            //de manera bruta ^
  }
}



El resultado será: ---------------------
el naipe1 es: 2 de Corazones
el naipe1 es: 2 de DIAMANTES


Si el enum esta en otro lado, entonces la forma de acceso es:
nombre de la clase + punto + nombre del enumerado + punto + valor


  • Utilizar la sentecia import static.
import static EjE.Palo.*; //sirve para no tener que escribir de donde lo ponemos es decir para no pones Palo.CORAZONES Y solo 
//poner CORAZONES

No es necesario abusar.



  • Crear métodos y clases abstractas.
¿cómo hace un animal? no se sabe sabemos como hace un Perro o un Tigre pero un Anima (¿Qué animal?) para eso nos sirve las clases abstractas para definir que hace pero no cómo.

Las clases abstractas no se pueden instanciar pero sirve con:
Herencia
Polimorfismo

Es valido:
public abstract class A{}
abstract public class A{}

Método
public abstract void comer(); 

Si hay al menos un método abstracto entonces la clase debe ser definida como abstract.

Si heredas de un una clase abstract, entonces debes implementar los métodos abstractos y darle cuerpo.

Pueden tener métodos abstractos o no Abstractos.

Para utilizar un método no abstracto en una clase abstracta debes de instanciar un hijo y ya puedes acceder a el.


UNA CLASE HEREDA DE OTRA CLASE, NO IMPLEMENTA OTRA CLASE.
UNA CLASE IMPLEMENTA INTERFACES

****
SI UNA CLASE ES ABSTRACTA Y HEREDA DE OTRA CLASE ABSTRACTA NO ES NECESARIO QUE IMPLEMENTE LOS MÉTODOS DE LA CLASE PADRE.

Es decir si heredas de una clase abstract
O implementas sus métodos abstrac O haces la clase hija en abstrac


Los atributos no se declaran abstrac.



  • Crear y utilizar un interface.
Una interfaz es un contrato ( obligación ) que debemos de cumplir, si implementas una interfaz tienes que darle cuerpo a todos y cada uno de los métodos, aunque ese cuerpo solo tenga {  /* un comentario */ }, pero con que tenga las llaves eso significa que ya tiene cuerpo.

Indican que hacer. Y cada clase que implementa decide cómo lo vamos a utilizar.

se definen public interface nombre{}

Todos lo métodos por definición son publicos y abstractos (de una interfaz) aun cuando no le pongas public.

Las variables también se pueden inicializar en el inicializador y en en un contructor.

Una interfaz puede HEREDAR de UNA o MÁS interfaces. MÁS NO IMPLEMENTAR.

UNA INTERFAZ NO implementar DE NADA


Una clase puede heredar de una clase e Implementar de una o más interfaces.

//todos los métodos por definición son abstractos por lo tanto no llevan cuerpo 


Si una clase la marcas como abstracta no es necesario que le des cuerpo a todos los métodos de las interfaces o clases abstractas.

Todos los métodos sobrescritos de una interfaz son publicos por definición y sólo public.

lleve o no lleve el public abstract los métodos de una interfaz son public abstrac.

aun cuando tenga la combinación
public abstract void  m();
abstract void  m();
public void  m();

Todas son public abstract


Los modificadores de una variable en una itnerfaz sólo pueden ser
public
static
final 

cada uno por separado o los tres juntos.

Una clase abstract puede o no darle cuerpo a los métodos de la interfaz que hereda PERO como la clase que esta heredando no tiene por default el public abstract, hay que poner SÓLO el public porque si se pone abstract entonces no se le agregaría cuerpo.


se puede instanciar una interfaz siempre y cuando se implementen sus metodos



package ClasesInternas;


public interface Martillo {

    void golpear();
    
}

class TestMartillo{

    public static void main(String[] args) {
        Martillo a = new Martillo() {
            
            @Override
            public void golpear() {
                throw new UnsupportedOperationException("Not supported yet.");
            }
        };  //ojo con el ;
        
    }

}



  • Crear clases internas
Sólo puede existir una clase pública en el MISMO ARCHIVO .java, pero si puede haber public dentro de otra clase, de decir dentro de una clase puede haber otra publica o private, pero no FUERA.

--inicia archivo .java ---
public class A{

 public class B{

  //       Aquí puede haber más metodos iguales a los de la clase A pero no marca error porque estan en //diferente clases aun cuando la clase B esta dentro de A.
Aquí no se permiten metodo main
    

}
}

class C{ // esta no puede ser public.

//es totalmente diferente que las demás y puede tener metodo main.

}


--termina archivo .java

Otro Ejemplo


package ClasesInternas;

public class Ex {
   
    private int a = 27;
    private void m(){
        System.out.println("Metodo Externo");
    }
   
   public  class Interna{
       int a = 424;
        private void m(){ //este método es diferente al de la clase Ex
            System.out.println("Soy otro metodo interno");
        }
     
    }
   
}

class Test{
    public static void main(String[] args) {
        Ex e = new Ex();
        Ex.Interna oInterno = e.new Interna();
     
        System.out.println(""+oInterno.a);
       
       M m = new M();
    }
   
}

class M{
   
}


Al compilar una clase que contiene otra aparece en clases NO estaticas
Ex.class //clase que tiene más
Ex$Interna.class //esta dentro de Ex

Si tenemos clases estáticas  la forma de INSTANCIAR es diferente


package ClasesInternas;

public class Ex {
   
    private int a = 27;
    private void m(){
        System.out.println("Metodo Externo");
    }
   
   public static class Interna{
       int a = 424;
        private void m(){ //este método es diferente al de la clase Ex
            System.out.println("Soy otro metodo interno");
        }
     
    }
   
}

class Test{
    public static void main(String[] args) {
        Ex e = new Ex();
        //Ex.Interna oInterno = e.new Interna();
       Ex.Interna oInterno = new Ex.Interna(); //OJO AQUI
        System.out.println(""+oInterno.a);
       
       M m = new M();
    }
   
}

class M{
   
}