A continuación dejo unos ejemplos de código con explicaciones. Estos ejemplos surgieron a partir de la realización de los ejercicios del capítulo 4 (Operators) del libro "Sun Certified Programmer for Java 6 Study Guide".
Para ver el post con el resumen de dicho capítulo haz click aquí.
Cada ejemplo tiene un link para visualizar el código original desde el proyecto (SVN) google.
Para ver el post con el resumen de dicho capítulo haz click aquí.
Cada ejemplo tiene un link para visualizar el código original desde el proyecto (SVN) google.
EJEMPLO 1 (Ver código original)
01. public class Feline {
02. public static void main(String[] args) {
03. Long x = 42L;
04. Long y = 44L;
05. System.out.print(" " + 7 + 2 + " ");
06. System.out.print(foo() + x + 5 + " ");
07. System.out.print(x + y + foo());
08. }
09. static String foo() { return "foo"; }
10. }
/*
SALIDA:
72 foo425 86foo
*/
02. public static void main(String[] args) {
03. Long x = 42L;
04. Long y = 44L;
05. System.out.print(" " + 7 + 2 + " ");
06. System.out.print(foo() + x + 5 + " ");
07. System.out.print(x + y + foo());
08. }
09. static String foo() { return "foo"; }
10. }
/*
SALIDA:
72 foo425 86foo
*/
Las concatenaciones se ejecutan de izquierda a derecha. Se pueden realizar concatenaciones entre diferentes tipos de operandos, es decir, se pueden concatenar tipos primitivos con objetos o viceversa (una concatenación de un objeto se traduce en el llamado al método toString(), para ver una explicación más detallada de la concatenación de objetos ver el ejemplo ConcatenacionObejtos.java).
En resumen, si el primer operando de una concatenación es un String se tomarán todos los siguientes como cadenas (línea 5 y 6). En caso contrario, se realizarán todas las operaciones de adición hasta que aparezca la primer cadena de caracteres, la cuál provocará que se tome todos los demás valores como cadenas (línea 7).
EJEMPLO 2 (Ver código original)
En resumen, si el primer operando de una concatenación es un String se tomarán todos los siguientes como cadenas (línea 5 y 6). En caso contrario, se realizarán todas las operaciones de adición hasta que aparezca la primer cadena de caracteres, la cuál provocará que se tome todos los demás valores como cadenas (línea 7).
EJEMPLO 2 (Ver código original)
01. public class SpecialOps {
02. public static void main(String[] args) {
03. String s = "";
04. Boolean b1 = true;
05. Boolean b2 = false;
06. if((b2 = false) | (21%5) > 2) s += "x";
07. if(b1 || (b2 = true)) s += "y";
08. if(b2 == true) s += "z";
09. System.out.println(s);
10. }
11. }
/*
SALIDA:
y
*/
02. public static void main(String[] args) {
03. String s = "";
04. Boolean b1 = true;
05. Boolean b2 = false;
06. if((b2 = false) | (21%5) > 2) s += "x";
07. if(b1 || (b2 = true)) s += "y";
08. if(b2 == true) s += "z";
09. System.out.println(s);
10. }
11. }
/*
SALIDA:
y
*/
En la línea 6 la primera expresión es una asignación (b2 = false). El resultado de cualquier expresión de asignación es el valor de la variable después de la asignación. La sustitución del operador == por = funciona solo con las variables booleanas (debido a que el bloque if solo puede comprobar expresiones booleanas).
En el caso de una variable de tipo int, por ejemplo:
int x = 0;
if (x = 2) {}
El código anterior daría un error de compilación, ya que el resultado de la asignación sería el valor 2. Un valor entero no puede ser utilizado donde se necesita un valor booleano.
En el caso de una variable de tipo int, por ejemplo:
int x = 0;
if (x = 2) {}
El código anterior daría un error de compilación, ya que el resultado de la asignación sería el valor 2. Un valor entero no puede ser utilizado donde se necesita un valor booleano.
A continuación dejo unos ejemplos de código con explicaciones. Estos ejemplos surgieron a partir de la realización de los ejercicios del capítulo 3 (Assignments) del libro "Sun Certified Programmer for Java 6 Study Guide".
Para ver el post con el resumen de dicho capítulo haz click aquí.
Cada ejemplo tiene un link para visualizar el código original desde el proyecto (SVN) google.
Para ver el post con el resumen de dicho capítulo haz click aquí.
Cada ejemplo tiene un link para visualizar el código original desde el proyecto (SVN) google.
EJEMPLO 1 (Ver código original)
01. class Alien {
02. String invade(short ships) { return "a few"; }
03. String invade(short... ships) { return "many"; }
04. }
05. public class Defender {
06. public static void main(String[] args) {
07. System.out.println(new Alien().invade(7));
08. }
09. }
/*
Defender.java:7: cannot find symbol
symbol : method invade(int)
location: class Alien
System.out.println(new Alien().invade(7));
^
1 error
*/
02. String invade(short ships) { return "a few"; }
03. String invade(short... ships) { return "many"; }
04. }
05. public class Defender {
06. public static void main(String[] args) {
07. System.out.println(new Alien().invade(7));
08. }
09. }
/*
Defender.java:7: cannot find symbol
symbol : method invade(int)
location: class Alien
System.out.println(new Alien().invade(7));
^
1 error
*/
Al compilar el código anterior se produce un error en la línea 7. Esto sucede debido a que se pasa como argumento el valor 7. El literal 7 (a secas) es de tipo int. Como no existe ninguna versión del método invade() que tome un valor int, se genera el error "cannot find symbol".
Para que este ejemplo funcione correctamente es necesario realizar un casteo del literal 7 hacia el tipo short, como lo muestra la línea siguiente:
System.out.println(new Alien().invade((short) 7));
De este modo el programa se ejecutaría correctamente, y su salida sería:
a few
EJEMPLO 2 (Ver código original)
EJEMPLO 3 (Ver código original)
EJEMPLO 4 (Ver código original)
Para que este ejemplo funcione correctamente es necesario realizar un casteo del literal 7 hacia el tipo short, como lo muestra la línea siguiente:
System.out.println(new Alien().invade((short) 7));
De este modo el programa se ejecutaría correctamente, y su salida sería:
a few
EJEMPLO 2 (Ver código original)
01. public class Dims {
02. public static void main(String[] args) {
03. int[][] a = {{1, 2, }, {3, 4}};
04. int[] b = (int[]) a[1];
05. Object o1 = a;
06. int[][] a2 = (int[][]) o1;
07. int[] b2 = (int[]) o1;
08. System.out.println(b[1]);
09. }
10. }
/*
Exception in thread "main" java.lang.ClassCastException: [[I cannot be cast to [
I
at Dims.main(Dims.java:7)
*/
02. public static void main(String[] args) {
03. int[][] a = {{1, 2, }, {3, 4}};
04. int[] b = (int[]) a[1];
05. Object o1 = a;
06. int[][] a2 = (int[][]) o1;
07. int[] b2 = (int[]) o1;
08. System.out.println(b[1]);
09. }
10. }
/*
Exception in thread "main" java.lang.ClassCastException: [[I cannot be cast to [
I
at Dims.main(Dims.java:7)
*/
Cuando se intenta compilar el código anterior la misma falla, debido a que (en la línea 7) se realiza una conversión erronea (ClassCastException). Esto se debe a que la variable o1 almacena una referencia a un arreglo de tipo int[][] y se intenta castear el mismo a uno de tipo int[].
Para visualizar la salida de este programa se podría comentar la línea 7, o reemplazarla con el código siguiente:
int[] b2 = (int[]) ((int[][]) o1)[0];
De esta manera lo que se hace es:
Para visualizar la salida de este programa se podría comentar la línea 7, o reemplazarla con el código siguiente:
int[] b2 = (int[]) ((int[][]) o1)[0];
De esta manera lo que se hace es:
- Castear el objeto o1 hacia un arreglo de tipo int[][].
- Tomar el primer arreglo simple dentro del arreglo multidimensional (o1).
- Realizar una conversión explícita del arreglo al tipo int[] (la cuál es redudante, ya que se haría implicitamente).
- Finalmente se asigna a la variable de referencia b2 el valor de referencia del arreglo simple.
EJEMPLO 3 (Ver código original)
01. public class Bridge {
02. public enum Suits {
03. CLUBS(20), DIAMONDS(20), HEARTS(30), SPADES(30),
04. NOTRUMP(40) {
05. public int getValue(int bid) {
06. return ((bid-1)*30) + 40;
07. }
08. };
09. Suits(int points) {
10. this.points = points;
11. }
12. private int points;
13. public int getValue(int bid) {
14. return points * bid;
15. }
16. }
17. public static void main(String[] args) {
18. System.out.println(Suits.NOTRUMP.getValue(3));
19. System.out.println(Suits.SPADES + " " + Suits.SPADES.points);
20. System.out.println(Suits.values());
21. }
22. }
/*
SALIDA:
100
SPADES 30
[LBridge$Suits;@addbf1
*/
02. public enum Suits {
03. CLUBS(20), DIAMONDS(20), HEARTS(30), SPADES(30),
04. NOTRUMP(40) {
05. public int getValue(int bid) {
06. return ((bid-1)*30) + 40;
07. }
08. };
09. Suits(int points) {
10. this.points = points;
11. }
12. private int points;
13. public int getValue(int bid) {
14. return points * bid;
15. }
16. }
17. public static void main(String[] args) {
18. System.out.println(Suits.NOTRUMP.getValue(3));
19. System.out.println(Suits.SPADES + " " + Suits.SPADES.points);
20. System.out.println(Suits.values());
21. }
22. }
/*
SALIDA:
100
SPADES 30
[LBridge$Suits;@addbf1
*/
El ejemplo de código anterior tiene tres líneas de salida:
- El valor NOTRUMP del enum Suits tiene sobreescrito el método getValue(int bird). Es por este motivo que cuando se invoca el método getValue() no se invoca la versión orginal.
- La línea Suits.SPADES devuelve el valor de la constante como un String.
- El método values() sobre el enum Suits devuelve una referencia a un arreglo, es por esto que se muestra el valor de referencia en vez de mostrar los valores del enum.
EJEMPLO 4 (Ver código original)
01. public class Ouch {
02. static int ouch = 7;
03. public static void main(String[] args) {
04. new Ouch().go(ouch);
05. System.out.print(" " + ouch);
06. }
07. void go(int ouch) {
08. ouch++;
09. for(int ouch = 3; ouch < 6; ouch++)
10. ;
11. System.out.print(" " + ouch);
12. }
13. }
/*
Ouch.java:9: ouch is already defined in go(int)
for(int ouch = 3; ouch < 6; ouch++)
^
1 error
*/
02. static int ouch = 7;
03. public static void main(String[] args) {
04. new Ouch().go(ouch);
05. System.out.print(" " + ouch);
06. }
07. void go(int ouch) {
08. ouch++;
09. for(int ouch = 3; ouch < 6; ouch++)
10. ;
11. System.out.print(" " + ouch);
12. }
13. }
/*
Ouch.java:9: ouch is already defined in go(int)
for(int ouch = 3; ouch < 6; ouch++)
^
1 error
*/
Este error se genera debido a que se esta definiendo una variable con un nombre que ya existe para ese ámbito. Es decir, el nombre de la variable del parámetro del método go() es ouch, el error se genera al utilizar este mismo nombre dentro del bloque for (dentro del mismo método o mismo ámbito).
EJEMPLO 5 (Ver código original)
EJEMPLO 5 (Ver código original)
01. public class Bertha {
02. static String s = "";
03. public static void main(String[] args) {
04. int x = 4;
05. Boolean y = true;
06. short[] sa = {1, 2, 3};
07. doStuff(x, y);
08. doStuff(x);
09. doStuff(sa, sa);
10. System.out.println(s);
11. }
12. static void doStuff(Object o) { s += "1"; }
13. static void doStuff(Object... o) { s += "2"; }
14. static void doStuff(Integer... i) { s += "3"; }
15. static void doStuff(Long l) { s += "4"; }
16. }
/*
SALIDA:
212
*/
02. static String s = "";
03. public static void main(String[] args) {
04. int x = 4;
05. Boolean y = true;
06. short[] sa = {1, 2, 3};
07. doStuff(x, y);
08. doStuff(x);
09. doStuff(sa, sa);
10. System.out.println(s);
11. }
12. static void doStuff(Object o) { s += "1"; }
13. static void doStuff(Object... o) { s += "2"; }
14. static void doStuff(Integer... i) { s += "3"; }
15. static void doStuff(Long l) { s += "4"; }
16. }
/*
SALIDA:
212
*/
La salida del código de ejemplo anterior se genera a partir de tres invocaciones al método doStuff() con distintos parámetros:
'2': Resultado de la invocación de la línea 7. El método se invoca con un valor de tipo int y uno Boolean.
doStuff(Object... o): Para el argumento de tipo int se hace un autoboxing hacia el tipo Integer. Como Integer y Boolean cumplen la relación ES-UN con el tipo Object, esta es la versión que se ejecuta.
doStuff(Integer... i): Este método no se invoca debido a que el tipo Boolean NO ES-UN Integer.
'1': Resultado de la invocación de la línea 8. El método se invoca con un valor de tipo int.
doStuff(Object o): Para el argumento de tipo int se hace un autoboxing hacia el tipo Integer. Como Integer cumple la relación ES-UN con el tipo Object, esta es la versión que se ejecuta.
doStuff(Long l): Este método no se invoca debido a que el tipo Integer no cumple la relación ES-UN con el tipo Long.
'2': Resultado de la invocación de la línea 9. El método se invoca con dos argumentos de tipo short[].
doStuff(Object... o): Ambos argumentos son arreglos (es decir, objetos), los mismos se generalizan al tipo Object.
doStuff(Integer... i): Este método no se invoca debido a que el tipo short[] no cumple la relación ES-UN con el tipo Integer.
'2': Resultado de la invocación de la línea 7. El método se invoca con un valor de tipo int y uno Boolean.
doStuff(Object... o): Para el argumento de tipo int se hace un autoboxing hacia el tipo Integer. Como Integer y Boolean cumplen la relación ES-UN con el tipo Object, esta es la versión que se ejecuta.
doStuff(Integer... i): Este método no se invoca debido a que el tipo Boolean NO ES-UN Integer.
'1': Resultado de la invocación de la línea 8. El método se invoca con un valor de tipo int.
doStuff(Object o): Para el argumento de tipo int se hace un autoboxing hacia el tipo Integer. Como Integer cumple la relación ES-UN con el tipo Object, esta es la versión que se ejecuta.
doStuff(Long l): Este método no se invoca debido a que el tipo Integer no cumple la relación ES-UN con el tipo Long.
'2': Resultado de la invocación de la línea 9. El método se invoca con dos argumentos de tipo short[].
doStuff(Object... o): Ambos argumentos son arreglos (es decir, objetos), los mismos se generalizan al tipo Object.
doStuff(Integer... i): Este método no se invoca debido a que el tipo short[] no cumple la relación ES-UN con el tipo Integer.
Ejemplos de código - Orientación a Objetos
lunes, 27 de julio de 2009
by
Matías Emiliano Alvarez Durán
A continuación dejo unos ejemplos de código con explicaciones. Estos ejemplos surgieron a partir de la realización de los ejercicios del capítulo 2 (Object Orientation) del libro "Sun Certified Programmer for Java 6 Study Guide".
Para ver el post con el resumen de dicho capítulo haz click aquí.
Cada ejemplo tiene un link para visualizar el código original desde el proyecto (SVN) google.
EJEMPLO 1 (Ver código original)
El casteo explícito (línea 23) provoca que el compilador tome la expresión ((Dog) new Hound()) como de tipo Dog. Como la clase Dog no contiene un método sniff(), se genera el error de compilación "cannot find symbol".
Si no se haría la generalización al tipo Dog, o se agregará una especialización al tipo Hound como la siguiente: ((Hound) ((Dog) new Hound())).sniff(); el programa compilaría y se ejecutaría correctamente.
Por otro lado, al comentar la línea 23 de este ejemplo, la salida sería la siguiente: how1 how1. Esto demuestra que más allá de que se realice la generalización de la línea 22, se invoca la versión del método bark() de la clase Hound. Esto se debe a que la selección de las versiones de los distintos métodos sobreescritos, se hace en tiempo de ejecución, y depende del tipo de objeto instanciado.
En conclusión llegamos a que el código original de este ejemplo, en tiempo de ejecución funcionaría correctamente (porque se invocaría al método sniff() de un objeto Hound). Pero como el compilador no encuentra la declaración del método sniff() en la clase padre,
genera un error de compilación. (Para comprobar lo dicho anteriormente se podría declarar un método sniff() con cualquier cuerpo en la clase Dog, el cuál en tiempo de ejcución nunca sería invocado por este ejemplo.)
EJEMPLO 2 (Ver código original)
Si comentáramos la línea 10 (la cuál provoca la excepción ClassCastException en tiempo de ejecución) y luego ejecutaríamos el programa, obtendríamos la siguiente SALIDA:
Exception in thread "main" java.lang.ClassCastException: Tree cannot be cast to
Redwood
at Redwood.go(Redwood.java:7)
at Redwood.main(Redwood.java:3)
Esto demuestra que el casteo (o especialización) de un objeto Tree hacia Redwood generá una excepción en tiempo de ejecución.
Entonces, se puede concluir que NO se puede realizar una especialización de un tipo base a un subtipo. Es decir, si tenemos una variable de referencia a un subtipo e intentamos asignarle un supertipo obtendremos un error (en este caso de compilación "incompatible types").
Lo mismo sucedería (como lo demuestra este ejemplo) al castear un supertipo hacia un subtipo (pero en este caso es un error un tiempo de ejecución).
EJEMPLO 3 (Ver código original)
En general, los métodos sobrecargados con argumentos var-arg son elegidos últimos (para ser ejecutados). Cabe destacar que los arrays son objetos, por este motivo la invocación de la línea 8 ejecuta la versión del método con el parámetro Object.
Entonces se podría decir que ciertos métodos tienen mayores posibilidades de ser ejecutados:
Para ver el post con el resumen de dicho capítulo haz click aquí.
Cada ejemplo tiene un link para visualizar el código original desde el proyecto (SVN) google.
EJEMPLO 1 (Ver código original)
01. class Dog {
02. public void bark() {
03. System.out.print("woof ");
04. }
05. }
06.
07. class Hound extends Dog {
08. public void sniff() {
09. System.out.print("sniff ");
10. }
11. public void bark() {
12. System.out.print("how1 ");
13. }
14. }
15.
16. public class DogShow {
17. public static void main(String[] args) {
18. new DogShow().go();
19. }
20. void go() {
21. new Hound().bark();
22. ((Dog) new Hound()).bark();
23. ((Dog) new Hound()).sniff();
24. }
25. }
/*
DogShow.java:24: cannot find symbol
symbol : method sniff()
location: class Dog
((Dog) new Hound()).sniff();
^
1 error
*/
02. public void bark() {
03. System.out.print("woof ");
04. }
05. }
06.
07. class Hound extends Dog {
08. public void sniff() {
09. System.out.print("sniff ");
10. }
11. public void bark() {
12. System.out.print("how1 ");
13. }
14. }
15.
16. public class DogShow {
17. public static void main(String[] args) {
18. new DogShow().go();
19. }
20. void go() {
21. new Hound().bark();
22. ((Dog) new Hound()).bark();
23. ((Dog) new Hound()).sniff();
24. }
25. }
/*
DogShow.java:24: cannot find symbol
symbol : method sniff()
location: class Dog
((Dog) new Hound()).sniff();
^
1 error
*/
El casteo explícito (línea 23) provoca que el compilador tome la expresión ((Dog) new Hound()) como de tipo Dog. Como la clase Dog no contiene un método sniff(), se genera el error de compilación "cannot find symbol".
Si no se haría la generalización al tipo Dog, o se agregará una especialización al tipo Hound como la siguiente: ((Hound) ((Dog) new Hound())).sniff(); el programa compilaría y se ejecutaría correctamente.
Por otro lado, al comentar la línea 23 de este ejemplo, la salida sería la siguiente: how1 how1. Esto demuestra que más allá de que se realice la generalización de la línea 22, se invoca la versión del método bark() de la clase Hound. Esto se debe a que la selección de las versiones de los distintos métodos sobreescritos, se hace en tiempo de ejecución, y depende del tipo de objeto instanciado.
En conclusión llegamos a que el código original de este ejemplo, en tiempo de ejecución funcionaría correctamente (porque se invocaría al método sniff() de un objeto Hound). Pero como el compilador no encuentra la declaración del método sniff() en la clase padre,
genera un error de compilación. (Para comprobar lo dicho anteriormente se podría declarar un método sniff() con cualquier cuerpo en la clase Dog, el cuál en tiempo de ejcución nunca sería invocado por este ejemplo.)
01. class Dog {
02. public void bark() {
03. System.out.print("woof ");
04. }
05. public void sniff() {
06. System.out.print("sniff Dog");
07. }
08. }
02. public void bark() {
03. System.out.print("woof ");
04. }
05. public void sniff() {
06. System.out.print("sniff Dog");
07. }
08. }
EJEMPLO 2 (Ver código original)
01. public class Redwood extends Tree {
02. public static void main(String[] args) {
03. new Redwood().go();
04. }
05. void go() {
06. go2(new Tree(), new Redwood());
07. go2((Redwood) new Tree(), new Redwood());
08. }
09. void go2(Tree t1, Redwood r1) {
10. Redwood r2 = (Redwood)t1;
11. Tree t2 = (Tree)r1;
12. }
13. }
14. class Tree {}
/*
SALIDA:
Exception in thread "main" java.lang.ClassCastException: Tree cannot be cast to
Redwood
at Redwood.go2(Redwood.java:10)
at Redwood.go(Redwood.java:6)
at Redwood.main(Redwood.java:3)
*/
02. public static void main(String[] args) {
03. new Redwood().go();
04. }
05. void go() {
06. go2(new Tree(), new Redwood());
07. go2((Redwood) new Tree(), new Redwood());
08. }
09. void go2(Tree t1, Redwood r1) {
10. Redwood r2 = (Redwood)t1;
11. Tree t2 = (Tree)r1;
12. }
13. }
14. class Tree {}
/*
SALIDA:
Exception in thread "main" java.lang.ClassCastException: Tree cannot be cast to
Redwood
at Redwood.go2(Redwood.java:10)
at Redwood.go(Redwood.java:6)
at Redwood.main(Redwood.java:3)
*/
Si comentáramos la línea 10 (la cuál provoca la excepción ClassCastException en tiempo de ejecución) y luego ejecutaríamos el programa, obtendríamos la siguiente SALIDA:
Exception in thread "main" java.lang.ClassCastException: Tree cannot be cast to
Redwood
at Redwood.go(Redwood.java:7)
at Redwood.main(Redwood.java:3)
Esto demuestra que el casteo (o especialización) de un objeto Tree hacia Redwood generá una excepción en tiempo de ejecución.
Entonces, se puede concluir que NO se puede realizar una especialización de un tipo base a un subtipo. Es decir, si tenemos una variable de referencia a un subtipo e intentamos asignarle un supertipo obtendremos un error (en este caso de compilación "incompatible types").
Lo mismo sucedería (como lo demuestra este ejemplo) al castear un supertipo hacia un subtipo (pero en este caso es un error un tiempo de ejecución).
EJEMPLO 3 (Ver código original)
01. class A {}
02. class B extends A {}
03. public class ComingThru {
04. static String s = "-";
05. public static void main(String[] args) {
06. A[] aa = new A[2];
07. B[] ba = new B[2];
08. sifter(aa);
09. sifter(ba);
10. sifter(7);
11. System.out.println(s);
12. }
13. static void sifter(A[]... a2) { s += "1"; }
14. static void sifter(B[]... b1) { s += "2"; }
15. static void sifter(B[] b1) { s += "3"; }
16. static void sifter(Object o) { s += "4"; }
17. }
/*
SALIDA:
-434
*/
02. class B extends A {}
03. public class ComingThru {
04. static String s = "-";
05. public static void main(String[] args) {
06. A[] aa = new A[2];
07. B[] ba = new B[2];
08. sifter(aa);
09. sifter(ba);
10. sifter(7);
11. System.out.println(s);
12. }
13. static void sifter(A[]... a2) { s += "1"; }
14. static void sifter(B[]... b1) { s += "2"; }
15. static void sifter(B[] b1) { s += "3"; }
16. static void sifter(Object o) { s += "4"; }
17. }
/*
SALIDA:
-434
*/
En general, los métodos sobrecargados con argumentos var-arg son elegidos últimos (para ser ejecutados). Cabe destacar que los arrays son objetos, por este motivo la invocación de la línea 8 ejecuta la versión del método con el parámetro Object.
Entonces se podría decir que ciertos métodos tienen mayores posibilidades de ser ejecutados:
- Parámetros con el tipo idéntico (como el caso de la invocación de la línea 9).
- Parámetros con el supertipo u Object (como el caso de las invocaciones de las líneas 8 y 10).
- Por último si los argumentos no concuerdan con ningún otro método, se ejecutan los métodos con parámetros var-arg.





