Cómo almacenar datos en objetos Java

Última actualización: enero de 2020

Aunque el botón de repetición es probablemente el botón más utilizado en un reloj despertador, incluso una AlarmClockclase sencilla necesita algunas funciones más. Por ejemplo, es posible que desee controlar cuánto tiempo permanecerá la alarma en modo de repetición. Para agregar dicha característica, debe comprender cómo Java controla los datos.

Los desarrolladores usan variables en Java para almacenar datos, y todas las variables tienen un tipo de datos y un nombre. El tipo de datos determina los valores que puede contener una variable. En este tutorial, aprenderá cómo los tipos integrales contienen números enteros, los tipos de punto flotante contienen números reales y los tipos de cadena contienen cadenas de caracteres. Luego, comenzará a usar variables de instancia en sus clases de Java.

Variables y tipos primitivos

Los tipos primitivos denominados, los tipos integrales y de punto flotante son los tipos de datos más simples en Java. El siguiente programa ilustra el tipo integral, que puede contener números enteros tanto positivos como negativos. Este programa también ilustra comentarios, que documentan su código pero no afectan al programa de ninguna manera.

/ * * Esto también es un comentario. El compilador ignora todo, desde * el primer / * hasta una "barra diagonal" que finaliza el comentario. * * Aquí está la "barra de estrella" que finaliza el comentario. * / public class IntegerTest {public static void main (String [] args) {// Aquí está la declaración de una variable int llamada anInteger, // a la que le da un valor inicial de 100. int anInteger = 100; // Declarar e inicializar un entero System.out.println (anInteger); // Resultados 100 // También puede hacer aritmética con tipos primitivos, utilizando los // operadores aritméticos estándar. anInteger = 100 + 100; System.out.println (anInteger); // Salidas 200}}

Java también usa tipos de punto flotante, que pueden contener números reales, es decir, números que incluyen un lugar decimal. Aquí hay un programa de ejemplo:

public class DoubleTest {public static void main (String [] args) {// Aquí está la declaración de una variable doble llamada aDouble. // También le das a aDouble un valor inicial de 5.76. doble aDouble = 5.76; // Declarar e inicializar aDouble System.out.println (aDouble); // Resultados 5.76 // También puedes hacer aritmética con tipos de coma flotante. aDoble = 5,76 + 1,45; System.out.println (aDouble); // Resultados 7.21}}

Intente ejecutar los programas anteriores. Recuerde, debe compilar antes de poder ejecutarlos:

javac * .java java IntegerTest java DoubleTest 

Java utiliza cuatro tipos integrales y dos tipos de punto flotante, que contienen diferentes rangos de números y ocupan diferentes cantidades de espacio de almacenamiento, como se muestra en las tablas siguientes.

Tipos integrales

TIPO Byte Corto En t Largo
TAMAÑO (bits) 8 dieciséis 32 64
RANGO -128 hasta 127 -32.768 hasta 32.767 -2,147,483,648 a 2,147,483,647 -263 al 263-1

Tipos de coma flotante (formato IEEE 754)

 
TIPO Punto flotante de precisión simple Punto flotante de doble precisión
TAMAÑO (bits) 32 64
RANGO +/- 1,18x10-38 a +/- 3,4x1038 +/- 2.23x10-308 a +/- 1.8x10308

Un tipo de cadena contiene cadenas y las maneja de manera diferente a la forma en que los tipos de punto flotante e integral manejan números. El lenguaje Java incluye una Stringclase para representar cadenas. Declara una cadena usando el tipo Stringy la inicializa con una cadena entre comillas, una secuencia de caracteres contenida entre comillas dobles, como se muestra a continuación. También puede combinar dos cadenas con el +operador.

// Fragmento de código // Declaración de la variable s de tipo String, // e inicialización con la cadena entre comillas "Hello". String s = "Hola"; // Concatenación de cadena en s con cadena entre comillas "Mundo" Cadena t = s + "Mundo"; System.out.println (t); // Salidas Hello World

Alcance variable

Además del tipo, el alcance también es una característica importante de una variable. El alcance establece cuándo se crea y destruye una variable y dónde un desarrollador puede acceder a la variable dentro de un programa. El lugar en su programa donde declara la variable determina su alcance.

Hasta ahora, he discutido las variables locales , que contienen datos temporales que usa dentro de un método. Declaras variables locales dentro de los métodos y solo puedes acceder a ellas desde esos métodos. Esto significa que puede recuperar solo las variables locales anInteger, que utilizó en IntegerTesty en las aDoubleque utilizó DoubleTest, del método principal en el que se declararon y en ningún otro lugar.

Puede declarar variables locales dentro de cualquier método. El siguiente código de ejemplo declara una variable local en el AlarmClock snooze()método:

public class AlarmClock {public void snooze () {// Tiempo de repetición en milisegundos = 5 segundos snoozeInterval = 5000; System.out.println ("ZZZZZ para:" + snoozeInterval); }}

Puede acceder snoozeIntervalsolo desde el snooze()método, que es donde declarósnoozeInterval, as shown here: 

AlarmClockTest de clase pública {public static void main (String [] args) {AlarmClock aClock = new AlarmClock (); aClock.snooze (); // Esto todavía está bien. // La siguiente línea de código es un ERROR . // No puede acceder a snoozeInterval fuera del método de repetición. snoozeInterval = 10000; }}

Parámetros del método

Un parámetro de método , que tiene un alcance similar a una variable local, es otro tipo de variable. Los parámetros de método pasan argumentos a métodos. Cuando declara el método, especifica sus argumentos en una lista de parámetros. Pasas los argumentos cuando llamas al método. Los parámetros del método funcionan de manera similar a las variables locales en el sentido de que se encuentran dentro del alcance del método al que están vinculados y se pueden utilizar en todo el método. Sin embargo, a diferencia de las variables locales, los parámetros del método obtienen un valor del llamador cuando llama a un método. Aquí hay una modificación del reloj de alarma que le permite pasar el snoozeInterval.

AlarmClock de clase pública {snooze público vacío (snoozeInterval largo) {System.out.println ("ZZZZZ para:" + snoozeInterval); }}
AlarmClockTest de clase pública {public static void main (String [] args) {AlarmClock aClock = new AlarmClock (); // Pase el intervalo de repetición cuando llame al método. aClock.snooze (10000); // Posponer durante 10000 ms. }}

Variables miembro: cómo almacenan datos los objetos

Las variables locales son útiles, pero debido a que solo proporcionan almacenamiento temporal, su valor es limitado. Dado que su vida útil abarca la duración del método en el que se declaran, las variables locales se comparan con un bloc de notas que aparece cada vez que recibe una llamada telefónica, pero desaparece cuando cuelga. Esa configuración puede ser útil para tomar notas, pero a veces necesitas algo más permanente. ¿Qué debe hacer un programador? Ingrese variables de miembro .

Las variables miembro, de las cuales hay dos, instancia y estática , forman parte de una clase.

Alcance y vida útil variables

Los desarrolladores implementan variables de instancia para contener datos útiles para una clase. Una variable de instancia se diferencia de una variable local en la naturaleza de su alcance y su duración. Toda la clase constituye el alcance de una variable de instancia, no el método en el que se declaró. En otras palabras, los desarrolladores pueden acceder a las variables de instancia en cualquier lugar de la clase. Además, la duración de una variable de instancia no depende de ningún método particular de la clase; es decir, su duración es la duración de la instancia que lo contiene.

Las instancias son los objetos reales que crea a partir del plano que diseña en la definición de clase. Declaras variables de instancia en la definición de clase, lo que afecta a cada instancia que creas desde el plano. Cada instancia contiene esas variables de instancia, y los datos contenidos dentro de las variables pueden variar de una instancia a otra.

Considere la AlarmClockclase. Pasar el método snoozeIntervalal snooze()método no es un gran diseño. Imagínese tener que escribir un intervalo de repetición en su reloj despertador cada vez que busca el botón de repetición. En su lugar, solo dale a todo el despertador un snoozeInterval. Completa esto con una variable de instancia en la AlarmClockclase, como se muestra a continuación:

public class AlarmClock {// Aquí declaras snoozeInterval. Esto lo convierte en una variable de instancia. // También lo inicializas aquí. long m_snoozeInterval = 5000; // Tiempo de repetición en milisegundos = 5 segundos. public void snooze () {// Todavía puedes acceder a m_snoozeInterval en un método AlarmClock // porque estás dentro del alcance de la clase. System.out.println ("ZZZZZ para:" + m_snoozeInterval); }}

Puede acceder a las variables de instancia casi en cualquier lugar dentro de la clase que las declara. Para ser técnico al respecto, declara la variable de instancia dentro del alcance de la clase y puede recuperarla desde casi cualquier lugar dentro de ese alcance. Hablando en términos prácticos, puede acceder a la variable en cualquier lugar entre el primer corchete que inicia la clase y el corchete de cierre. Dado que también declara métodos dentro del alcance de la clase, ellos también pueden acceder a las variables de instancia.

También puede acceder a variables de instancia desde fuera de la clase, siempre que exista una instancia y tenga una variable que haga referencia a la instancia. Para recuperar una variable de instancia a través de una instancia, usa el operador de punto junto con la instancia. Puede que esa no sea la forma ideal de acceder a la variable, pero por ahora, complétela de esta manera con fines ilustrativos:

public class AlarmClockTest {public static void main (String [] args) {// Crea dos relojes. Cada uno tiene su propio m_snoozeInterval AlarmClock aClock1 = new AlarmClock (); AlarmClock aClock2 = nuevo AlarmClock (); // Cambiar aClock2 // Pronto verá que hay formas mucho mejores de hacer esto. aClock2.m_snoozeInterval = 10000; aClock1.snooze (); // Posponer con el intervalo de aClock1 aClock2.snooze (); // Posponer con el intervalo de aClock2}}

Pruebe este programa y verá que aClock1todavía tiene su intervalo de 5,000 mientras que aClock2tiene un intervalo de 10,000. Nuevamente, cada instancia tiene sus propios datos de instancia.

No olvide que la definición de clase es solo un modelo, por lo que las variables de instancia no existen realmente hasta que cree instancias a partir del modelo. Cada instancia de una clase tiene su propia copia de las variables de instancia, y el plano define cuáles serán esas variables de instancia.

JavaWorld

Encapsulamiento

Encapsulation is one of the foundations of object-oriented programming. When using encapsulation, the user interacts with the type through the exposed behavior, not directly with the internal implementation. Through encapsulation, you hide the details of a type's implementation. In Java, encapsulation basically translates to this simple guideline: "Don't access your object's data directly; use its methods."

That is an elementary idea, but it eases our lives as programmers. Imagine, for example, that you wanted to instruct a Person object to stand up. Without encapsulation, your commands could go something like this: "Well, I guess you'd need to tighten this muscle here at the front of the leg, loosen this muscle here at the back of the leg. Hmmm -- need to bend at the waist too. Which muscles spark that movement? Need to tighten these, loosen those. Whoops! Forgot the other leg. Darn. Watch it -- don't tip over ..." You get the idea. With encapsulation, you would just need to invoke the standUp() method. Pretty easy, yes?

Some advantages to encapsulation:

  • Abstraction of detail: The user interacts with a type at a higher level. If you use the standUp() method, you no longer need to know all the muscles required to initiate that motion.
  • Isolation from changes: Changes in internal implementation don't affect the users. If a person sprains an ankle, and depends on a cane for a while, the users still invoke only the standUp() method.
  • Correctness: Users can't arbitrarily change the insides of an object. They can only complete what you allow them to do in the methods you write.

Here's a short example in which encapsulation clearly helps in a program's accuracy:

// Bad -- doesn't use encapsulation public class Person { int m_age; } public class PersonTest { public static void main(String[] args) { Person p = new Person(); p.m_age = -5; // Hey -- how can someone be minus 5 years old? } } // Better - uses encapsulation public class Person { int m_age; public void setAge(int age) { // Check to make sure age is greater than 0. I'll talk more about // if statements at another time. if (age > 0) { m_age = age; } } } public class PersonTest { public static void main(String[] args) { Person p = new Person(); p.setAge(-5); // Won't have any effect now. } } 

Incluso ese programa simple muestra cómo puede meterse en problemas si accede directamente a los datos internos de las clases. Cuanto más grande y complejo es el programa, más importante se vuelve la encapsulación. También recuerde que muchos programas comienzan siendo pequeños y luego crecen para durar indefinidamente, por lo que es esencial que los diseñe correctamente, desde el principio. Para aplicar encapsulación AlarmClock, simplemente puede crear métodos para manipular el intervalo de repetición.

Una nota sobre los métodos

Los métodos pueden devolver valores que utiliza la persona que llama. Para devolver un valor, declare un tipo de retorno no vacío y use una returndeclaración. El getSnoozeInterval()método que se muestra en el siguiente ejemplo ilustra esto.

Escribe el programa