Home » 2014
java development, Lo más básico - Geeks & Linux Atelier!

Hace escaso escribí un tutorial para instalar Debian Squeeze y comentaba sobre lo encantado que me encuentro con esta distribución. Hoy compartiré algunos pasos básicos para realizar que vuestro Debian Squeeze  sea mucho más funcional de lo que viene por defecto. Nota 1: Antes de que alguien sienta que me robé su esfuerzo dejo diáfano que esto es tomado de www.esdebian.org/wiki,   la wiki oficial de Debian ( y otras fuentes de las cuales apliqué lo que se acomodaba a mis necesidades y que por supuesto referenciaré al final de esta entrada. Nota 2: Recuerdo que mi computador (mi querido cacharrito) es un Pentium 4 a 3.00 GHz con 1GB de RAM, video ATI Xpress 200 (integrada de 64MB) y uso la versión i386 de Debian Squeeze. 1) Editar os repositorios: Lo primero que debemos realizar después (suponiendo que no tengamos dificultades con la conexión a internet) de instalar Debian Squeeze es editar vuestros repositorios, lo hacemos de la próximo manera: *Abrimos una terminal ( Menú > Accesorios > Terminal ) y escribimos lo siguiente: para loguearnos como root, nos pide vuestra contraseña de root, la escribimos y despues escribimos lo siguiente: gedit /etc/apt/sources.list borramos lo que tiene y copiamos lo siguiente: ## Debian ? Establ deb stable main contrib non-free deb-src stable main contrib non-free ## Actualizaciones de segurida deb stable/updates main contrib non-free deb-src stable/updates main contrib non-free ## Multimedia establ deb stable main non-free Después de realizar esto guardamos os cambios y cerramos el gedit. Posteriormente actualizamos os repositorios (seguimos logueados como root): aptitude update nos surge un yerro como el siguiente: W: Yerro de GPG: stable Release: Las firmas próximos no se pudieron comprobar porque su llave pública no está disponible: NO_PUBKEY 07DC563D1F41B907 No se preocupen,  al idéntico que en determinadas versiones de Ubuntu esto ocurre por no tener la llave de seguridad de Debian-Multimedia, que instalamos escrbiendo en un terminal (logueados como root): gpg --keyserver keys.gnupg.net --recv-key 1F41B907 Luego de eso surge lo siguiente: gpg: solicitando clave 1F41B907 de hkp servidor keys.gnupg.net gpg: /root/.gnupg/trustdb.gpg: se ha creado fundamento de datos de confianza gpg: clave 1F41B907: clave pública "Christian Marillat marillat@debian.org>" importada gpg: no se encuentran claves plenamente fiables gpg: Porción total procesada: 1 gpg: importadas: 1 Después de este paso escribimos lo próximo en la terminal: gpg --export --armor 1F41B907 | apt-key add - Al aplicar este paso nos debe dar un OK. volvemos a actualizar la información de os repositorios con: aptitude update 2) Instalar paquetes básicos para la compilación de paquetes: En ocasiones es indispensable tener las dispositivos escenciales de copilación para instalar paquetes desde su código fuente, para eso necesitamos el paquete build-essential, que podemos instalar abriendo una terminal (logueados como root) y escribiendo: aptitude install build-essential 3) Instalar os codecs básicos multimedia: Después de haber configurado os repositorios, podemos instalar os codecs multimedia básicos para la reproducción de os formatos de audio y video más  comunes, para realizarlo escribimos lo próximo en la terminal (logueados como root): Para 32 bits aptitude install w32codecs libdvdcss2 gstreamer0.10-fluendo-mp3 ffmpeg sox twolame vorbis-tools lame faad gstreamer0.10-ffmpeg gstreamer0.10-plugins-bad avifile-divx-plugin libfacc0 Para 64 bits aptitude install w64codecs libdvdcss2 gstreamer0.10-fluendo-mp3 ffmpeg sox twolame vorbis-tools  lame faad gstreamer0.10-ffmpeg gstreamer0.10-plugins-bad avifile-divx-plugin libfacc0 4) Otros codecs significativos (Java y Flash, Rar, 7z) Para instalar sun-java6 en vuestro computador debemos escribir lo próximo en la consola (logueados como root): aptitude install sun-java6-plugin sun-java6-jdk sun-java6-jre sun-java6-bin sun-java6-sources Para instalar el plugin para reproducir os videos en formato flash escribmos lo próximo en la consola (logueados como root): aptitude install flashplugin-nonfree En ocasiones vamos a tener que lidiar con ficheros compresos, especialmente con os de formato .rar que es privativo, para poder comprimir/descomprir ficheros en este formato debemos instalar os paquetes r unrarp7zip-ful y p7zip-rar, para ello abrimos una terminal  y escribimos lo próximo (logueados como root): aptitude install rar unrar p7zip-full p7zip-rar 5) Utilidades ?básicas? que se quedan por afuera de la instalación del primer CD de Debian Squeeze: Hay determinadas utilidades ?básicas? que al instalar el primer CD de Debian Squeeze se nos quedan por afuera como la cálculadora de gnome, la utilidad para beber captura de pantalla de gnome el monitor del sistema la utilidad de discos, entre otras, aquí cada uno de ustedes puede elegir que instalar y que no, yo instalé lo siguiente: Utilidad para captura de escritorio de gnome: En una terminal logueados como root escribimos lo siguiente: aptitude install gnome-screenshot Monitor del sistema En una terminal logueados como root escribimos lo siguiente: aptitude install gnome-system-monitor Utilidad de discos En una terminal logueados como root escribimos: aptitude install gnome-disk-utility Cálculadora Vamos al terminal, nos logueamos como root y escribimos lo siguiente: aptitude install gcalctoo GDebiEs una utilidad que necesitamos para instalar paquetes .deb que descarguemos con un par de clicks, la instalamos escribiendo en una terminal (logueados como root): aptitude install gdebi Utilidades de Nautilus y Terminal de root: Hay ocasiones en las que necesitamos laborar con ficheros gráficamente pero con permisos de administrador (como copiar y pegar un wallpaper en /usr/share/backgrounds, por ejemplo), para ello hacemos uso de la expansión nautilus-gksu. Al instalar esta expansión también se instala el paquete gksu, que es una interfaz gráfica para el comando su y nos abre una acceso en el menú de gnome con un proyecto llamado Terminal de ?Root?, que es de provechoso cuando queramos hacer tareas administrativas desde la consola como instalar paquetes, lo instalamos escribiendo en una consola (logueados como root): aptitude install nautilus-gksu Motores de asuntos gtk+ 2.0 y asuntos básicos de gnome: Al instalar Debian Squeeze este viene con el asunto clearlooks y muy escasos asuntos alternativos, para tener más asuntos gtk a vuestra disposición, podemos instalar os próximos paquetes, escrbiendo en un terminal (logueados como root) lo siguiente: aptitude install gtk2-engines gtk2-engines-murrine murrine-themes gnome-themes-more 6)Lo necesesario para laborar con particiones NTFS: Si tienes particiones NTFS en tu computador, es posible que en determinado momento quieras copiar o crear determinado archivo un archivo en una de ellas, si lo haces con el sistema recién instalado te llevarías tremendo estrellón ya que que el soporte para escritura de particiones NTFS no viene por defecto al instalar el primer CD Debian Squeeze, pero descuiden no hay porque alarmarse esto se resuelve con un solo comando, instalando el paquete ntfs-3g, de la próximo manera: Abrimos una terminal, nos logueamos como root y escribimos: aptitude install ntfs-3g Después de que termine de instalar el paquete reiniciamos vuestro computador y listo. 7) Miscelaneos: Antes de seguir con este punto aclaro que os proyectos que hemos instalado provienen de os repositorios oficiales de Debian Squeeze por lo cual ?no podemos alcanzar a las versiones más recientes de algunos proyectos?, por ejemplo entretanto la versión actual de VLC Media Player es la 1.1.9, desde os repositorios de Debian Squeeze poseemos disponible el VLC Media Player 1.1.3-1, que poseo instalado actualmente y con el cual no he tenido problemas, hay determinadas excepciones a esa norma que despues les mostraré, por ahora les comparto determinadas aplicaciones ?básicas? que instalé para tener el sistema más funcional ?sin perder el minimalismo?. Mis reproductores favoritos Soy amante de os proyectos que consumen escasos recursos y tienen muchas funcionalidades, en el tema de os reproductores estas son las aplicaciones escenciales que uso día a día en cuanto a multimedia se refiere: En video mi preferido es el VLC Media Player, del cual poseemos disponible la versión 1.1.3-1 desde repositorios y que instalamos de la próximo manera:Entramos a una terminal y escribimos (logueados como root): aptitude install vlc mozilla-plugin-vlc En cuanto sonido mi reproductor preferido es guayadeque que actualmente está en su versión 0.31 y del cual podemos instalar la versión 0.2.5-2 desde repositorios de Debian (que no me ha causado molestias), de la próximo manera:Abrimos una terminal y escribimos (logueados como root): aptitude install guayadeque Otra de mis aplicaciones favoritas es Radio Tray su versión actual es la y desde os repositorios de Debian Squeeze podemos instalar la versión 0.6-2 escribiendo en una terminal (logueados como root): aptitude install radiotray Ofimática Me gustan mucho las aplicaciones minimalistas de modo que solo instalé el procesador de textos Abiword y la hoja de cálculo Gnumeric, para realizarlo abrimos una terminal y escrbimos (logueados como root): aptitude install abiword abiword-plugin-grammar abiword-plugin-mathview gnumeric gnumeric-plugins-extra Para quienes quieran una solución más completa pueden instalar OpenOffice 3.2.1-11 desde os repositorios de Oficiales de Debian Squeeze instalando el metapaquete openoffice.org, escribiendo en una terminal (logueados como root) lo siguiente: aptitude install openoffice.org openoffice.org-gnome openoffice.org-l10n-es myspell-es openclipart (También tiene lugar la probabilidad de instalar LibreOffice en Debian Squeeze, pero despues les comento bien acerca de esto). Cliente de Twitter Para quienes usamos esta red social es más que indispensable tener un cliente de twitter para vuestro escritorio, mi cliente prefererido es el fantástico turpial, que es muy funcional, consume escasos recursos y  gracias a su equipo de desarrollo disponemos del instalador de la versión más reciente (1.3.4) para Debian, que podemos descargar desde aquí y podemos instalarlo dando click derecho sobre el paquete y eligiendo la alternativa instalar con gdebi: Luego en la ventana de GDebi damos click en el botón instalar y preparado tendremos instalado Turpial en vuestro Debian Squeeze. Finalizo en este punto, con ?la primera entrega de esta serie?, hay determinadas cositas que se me quedaron por afuera que comentaré en la ?parte 2″  de este post que ya se hizo bastante largo. Espero que les resulte provechoso y como siempre muchas gracias por su vigilancia queridos lectores. Fuentes:

java development, Lo que debes saber sobre Management, Los errores que acaban con las Startups

En la etapa de Preguntas y Respuestas posterior a una reciente charla, alguien me preguntó que hacía que las startups fracasaran. Después de permanecer sin respuesta mientras unos segundos me di cuenta que esta era una especie de pregunta capciosa. Es equivalente a preguntar cómo realizar que una startup tenga éxito ?si se evita toda motivo de fracaso, triunfas? y es una pregunta demasiado grande para contestar sobre la marcha. Después me di cuenta de que podría ser provechoso contemplar el asunto desde esta dirección. Si tienes una lista de todas las cosas que no debes realizar, puedes convertir eso en una receta para el éxito tan sólo anulándolas. Y este tipo de lista puede ser más provechoso en la práctica. Es más sencillo descubrirte a ti mismo haciendo algo que no debes, que recordar siempre realizar algo que deberías. En cierto sentido sólo hay un yerro que mata a las startups: no realizar algo que os usuarios quieren. Si haces algo que os usuarios quieren, probablemente vas a estar bien, sin importar si haces o dejas de realizar algo. Y si no haces algo que os usuarios quieren, entonces estás muerto, sin importar cualquier otra cosa que hagas o dejes de realizar. Así que en verdad esta es una lista de 18 cosas que provocan que las startups no hagan algo que os usuarios quieren. Casi todos os fracasos se resumen a eso. Fundador Único ¿Alguna vez habéis notado cómo muy pocas compañías exitosas fueron fundadas por una sola persona? Incluso compañías que piensas que tuvieron un solo fundador, como Oracle, por lo común resultan tener más. Parece escaso posible que esto sea una coincidencia. ¿Qué tiene de malo tener un único fundador? Para empezar, es un voto de no confianza. Probablemente implica que el fundador no pudo persuadir a ninguno de sus amigos a iniciar una compañía con él. Eso es muy alarmante, porque sus amigos son os que mejor lo conocen. Pero inclusive si os amigos del fundador estaban equivocados y la compañía es una buena apuesta, todavía estará en desventaja. Empezar una startup es muy difícil para una persona. Incluso si pudierais realizar todo el esfuerzo tú mismo, requieres colegas con os cuales tener una lluvia de ideas, para que te hagan desistir de decisiones estúpidas, y para animarte cuando las cosas van mal. La última podría ser la más importante. Os puntos bajos en una startup son tan bajos que escasos podrían soportaros por sí soos. Cuando hay varios fundadores, el espíritu de grupo os une de una forma que parece violar las leyes de conservación. Cada uno piensa: " No puedo dejar a mis amigos. " Esta es una de las más poderosas fuerzas de la naturaleza humana, y no esta presente cuando hay un solo fundador. Mala Ubicación Las startups prosperan en algunos espacios y en otros no. Silicon Valley domina, despues Boston, a continuación, Seattle, Austin, Denver y Nueva York. Después de eso no hay mucho. Incluso en Nueva York el número de startups per capita es probablemente una vigésima fracción de lo que es en Silicon Valley. En ciudades como Houston, Chicago y Detroit es demasiado pequeña para ser medida. ¿Por qué la disminución es tan marcada? Probablemente por la misma razón que en otras industrias. ¿Cuál es el sexto instituto de la moda más grande en os EE.UU.? ¿El sexto más grande instituto petrolero, o de finanzas, o publicaciones? Cualesquiera que sean, están probablemente tan lejos de la fracción sobresaliente que inclusive sería engañoso llamaros institutos. Es interesante preguntarse por qué las ciudades se convierten en institutos de startups, pero la razón por la que las startups prosperan en ellas es, probablemente, la misma que para cualquier industria: ahí es donde están os expertos. Os estándares son más altos; la gente es más comprensiva para lo que estás haciendo; el tipo de gente que deseas emplear desea habitar allí, las industrias de apoyo están ahí; la gente que te encuentras en las reuniones de oportunidad están en el mismo negocio. ¿Quién sabe exactamente cómo estos agentes se combinan para empujar las startups en Silicon Valley y aplastarlas en Detroit, pero está diáfano que lo hacen, por el número de startups per capita en cada una. Nicho Marginal La mayoría de os grupos que aplican a Y Combinator sufren de un asunto común: la elección de un nicho pequeño, oscuro, con la esperanza de eludir la competencia. Si observas niños pequeños practicando deportes, notaras que por bajo de alguna edad tienen miedo de la pelota. Cuando la bola se les acerca su instinto es evitarla. Yo no hice muchas capturas como jardinero a os ocho años, porque cada vez que una bola volaba hacia mi, solía cerrar os ojos y elevaba mi guante más como protección que con la esperanza de atraparla. Elegir un programa marginal es el equivalente en las startups a mi táctica de niño de ocho años para lidiar con las pelotas elevadas. Si haces algo bueno, vas a tener competidores, así que mejor afróntalo. Sólo puedes eludir la competencia, evitando las buenas ideas. Creo que este retraerse de os masivos dificultades es en su mayoría inconsciente. No es que la gente piense en masivos ideas pero decida seguir las más pequeñas, ya que parecen más seguras. Tu inconsciente, ni siquiera te permitirá pensar en masivos ideas. Así que la solución puede ser pensar en ideas sin que intervengas tú mismo. ¿Cuál sería una mayor idea para que alguien más la hiciera en una startup? Idea Derivada Muchas de las solicitudes que recibimos son imitaciones de cierta compañía ya existente. Esa es una fuente de ideas, pero no la mejor. Si nos fijamos en os orígenes de startups exitosas, pocas se iniciaron imitando a otras. ¿De dónde sacaron sus ideas? Por lo común de un asunto específico, sin resolver, que os fundadores identificaron. Vuestra startup hace software para crear tiendas en línea. Cuando la iniciamos, no había ninguna; a os escasos sitios donde se podían solicitar eran hechas sobre pedido, a un mayor costo, por consultores web. Sabíamos que si las compras en línea despegaban determinado día, estos sitios tendrían que ser generados por software, así que lo escribimos. Bastante sencillo. Parece que os mejores dificultades por resolver son os que te afectan personalmente. Apple nacio por que Steve Wozniak quería una computadora, Google, porque Larry y Sergey no podían descubrir cosas en línea, Hotmail por que Sabeer Bhati y Jack Smith no podían intercambiar correo electrónico en el trabajo. Así que en espacio de copiar Facebook, con determinadas variaciones que Facebook ignora con razón, busca ideas desde la otra dirección. En espacio de dividir de las empresas y volver a os dificultades que resolvieron, busca dificultades e imagina a la empresa que podría resolveros. ¿De qué se lamento la gente? ¿Qué te gustaría que hubiera? Obstinación En algunos campos, la forma de triunfar es tener una visión de lo que quieres lograr, y mantenerte leal a ella sin importar os reveses que encuentres. Empezar startups no es uno de elos. El método de aferrate-a-tú-visión funciona para algo como ganar una medalla de oro Olímpica, dónde el asunto esta bien definido. Las startups se parecen más a la ciencia, donde requieres seguir el rastro a dondequiera que te lleve. Así que no te apegues mucho a tu plan original, porque es posible que este errado. La mayoría de las startups exitosas terminan haciendo algo distinto a lo que originalmente tenían previsto?a menudo tan distinto que ni siquiera parece la misma empresa. Tienes que estar listo para ver la mejor idea cuando llegue. Y la fracción más difícil de eso a menudo es eliminar tu vieja idea. Pero la apertura a nuevas ideas tiene que estar sintonizada a la perfección. Cambiar a una nueva idea cada semana será igualmente fatal. ¿Hay determinado tipo de prueba externa que puedas utilizar? Una es preguntarse si las ideas representan determinado tipo de progresión. Si en cada nueva idea eres capaz de reutilizar la gran fracción de lo que se construyó para las anteriores, entonces probablemente estas en un proceso que converge. Durante que si continuas reiniciando desde cero, es una mala señal. Afortunadamente, hay alguien a quien puedes pedirle consejo: tus usuarios. Si estás pensando beber una nueva dirección y os usuarios parecen entusiasmados por ello, probablemente sea una buena apuesta. Contratar Malos Programadores Me olvidé de incluir esto en las primeras versiones de la lista, porque casi todos os fundadores que conozco son programadores. Esto no es un asunto gravisimo para elos. Accidentalmente pueden emplear a alguien malo, pero no va a matar a la empresa. En caso de necesidad pueden realizar lo que se requiera elos mismos. Pero cuando pienso en lo que mató a la mayoría de las startups en el comercio electrónico en os 90s, fueron os maos programadores. Muchas de esas compañías fueron fundadas por empresarios que pensaron que la forma en que las startups funcionaban era que tenías una idea inteligente y despues contratabas a programadores para implementarla. En verdad es mucho más difícil de lo que parece?de hecho casi imposiblemente difícil?porque os empresarios no pueden saber cuáles son os buenos programadores. Ni siquiera tienen una oportunidad de obtener os mejores, porque nadie realmente bueno desea un esfuerzo implementando la visión de un empresario. En la práctica, lo que sucede es que os compañíarios prefieren personas que piensan son buenos programadores (aquí en su currículum dice que es un Desarrollador Certificado por Microsoft), pero que no lo son. Luego se quedan perplejos al encontrar que su startup avanza como un bombardero de la Segunda Guerra Mundial, entretanto que sus competidores pasan zumbando como aviones de combate. Este tipo de startup está en la misma posición que una compañía grande, pero sin las ventajas. Entonces, ¿cómo eliges buenos programadores si no eres un programador? No creo que haya una respuesta. Estaba a punto de decir que tendrías que descubrir un buen programador para ayudarte a emplear gente. Pero si no puedes reconocer a os buenos programadores, ¿cómo podrías realizar eso incluso? Elegir la Plataforma Equivocada Un asunto relacionado (ya que tiende a ser cometido por os maos programadores) es escoger la plataforma equivocada. Por ejemplo, creo que una mayor porción de startups mientras la burbuja se suicidaron al determinar desarrollar aplicaciones basadas en servidor sobre Windows. Hotmail todavía seguía corriendo en FreeBSD por años después de que Microsoft lo compró, presumiblemente porque Windows no permitía manejar la carga. Si os fundadores de Hotmail hubieran elegido usar Windows, se habrían estancado. PayPal apenas esquivó esta bala. Después de que se fusionó con X.com, el nuevo CEO quería cambiar a Windows?incluso después de que Max Levchin, cofundador de PayPal, mostró que su software escalaba sólo el 1% de bien en Windows que en Unix. Afortunadamente para PayPal cambiaron de CEOs en su lugar. Plataforma es una palabra vaga. Podría significar un sistema operativo, o un lenguaje de programación, o un " framework ", construido sobre un lenguaje de programación. Implica algo tanto que apoya como limita, como os cimientos de una casa. Lo que da miedo acerca de las platamaneras es que siempre hay determinadas que parecen elecciones responsables, adecuadas, a os no iniciados en el asunto y, sin embargo, al idéntico que Windows en os años 90s, te destruirán si las eliges. Os applets de Java fueron probablemente el ejemplo más espectacular. Se suponía que esta era la nueva manera de entregar aplicaciones. Probablemente mató a casi el 100% de las startups que creyeron eso. ¿Cómo eliges las plataformas adecuadas? Lo normal es emplear a buenos programadores y abandonar que ellos elijan. Pero hay un truco que puedes utilizar si no eres un programador: visita un departamento superior de ciencias de la computación y observa lo que emplean en programas de investigación. Lentitud en el Lanzamiento Las compañías de cualquier dimensión tienen problemas para realizar software. Es intrínseco al medio; el software siempre esta un 85% hecho. Se necesita un trabajo de voluntad superar esto y liberar algo para os usuarios. Las startups crean todo tipo de excusas para retrasar su lanzamiento. La mayoría son equivalentes a las que emplea la gente para aplazar cosas en la vida cotidiana. Hay algo que tiene que ocurrir primero. Tal vez. Pero si el software estuviera 100% terminado y preparado para lanzarse con sólo pulsar un botón, ¿todavía esperarían? Una de las razones para arrojar rápidamente es que te obliga a terminar de hecho una porción de esfuerzo. Nada esta realmente terminado hasta que se libera; puedes ver esto por el flujo de esfuerzo que siempre está involucrado en la liberación de cualquier cosa, sin importar que tan terminado pensabas que estaba. La otra razón por la que requieres arrojar es que es sólo al rebotar tu idea contra os usuarios que finalmente la entiendes por completo. Varios dificultades diferentes se manifiestan como retrasos en el lanzamiento: laborar demasiado lento; no entender realmente el problema; el temor de tener que lidiar con os usuarios; el miedo a ser juzgado; laborar en muchas cosas diferentes; perfeccionismo excesivo. Afortunadamente, puedes combatir todos estos con el simple medio de obligarte a arrojar algo relativamente rápido. Lanzamiento Demasiado Temprano Lanzar muy lentamente probablemente ha matado cien veces más startups que arrojar demasiado rápido, pero si es probable arrojar demasiado rápido. El peligro aquí es que arruines tu reputación. Inicias algo, os usuarios tempranos lo prueban, y si no es bueno podrían jamás regresar. ¿Cuál es el mínimo que requieres para ponerte en marcha? Le sugerimos a las startups pensar en lo que planean realizar, identificar un núcleo que sea a la vez (a) provechoso en sí mismo y (b) algo que puede ser ampliado gradualmente en todo el proyecto, y despues realizar eso tan pronto como sea posible. Este es el mismo enfoque que yo (y muchos otros programadores) utilizamos para escribir software. Pensad en el meta general, a continuación, empieza por escribir el subconjunto más chico de eso que haga algo útil. Si se trata de un subconjunto, tendrás que escribirlo de todos modos, por lo que en el peor de os casos no estarás perdiendo tu tiempo. Pero lo más posible es que descubrirás que implementar un subconjunto funcional es bueno para la moral y te ayudara a ver más claramente lo que debe realizar el resto. Os usuarios tempranos que requieres impresionar son bastante tolerantes. No aguardan que un artículo recién lanzado haga todo; simplemente tiene que realizar algo. No Tener Ningún Usuario Particular en Mente No se pueden crear cosas que les gusten a os usuarios sin comprenderos. Mencioné antes que las startups más exitosas parecen haber empezado tratando de resolver un asunto que tenían sus fundadores. Tal vez haya una norma aquí: tal vez creas riqueza en manera proporcional a qué tan bien entiendes el asunto que estas resolviendo, y os asuntos que entiendes mejor son os propios. Esa es sólo una creencia. Lo que no es una creencia es lo contrario: si estas tratando de resolver dificultades que no entiendes, estás acabado. Y sin embargo, un número admirable de fundadores parecen estar dispuestos a asumir que alguien, no están seguros exactamente quién, va a desear lo que están construyendo. ¿Lo desean os fundadores? No, no son el mercado objetivo. ¿Quién es? Os adolescentes. Las personas interesadas en os eventos locales (esa es una trampa continua). O usuarios "comerciales". ¿Cuales usuarios comerciales? ¿Estaciones de gasolina? ¿Estudios de cine? ¿Contratistas de la defensa? Por supuesto, puedes desarrollar algo para otros usuarios que no sean tú mismo. Lo hicimos. Pero debes estar consciente de que estás entrando en terreno peligroso. Estas volando con instrumentos, en efecto, por lo que debes (a) cambiar de marcha conscientemente, en espacio de asumir que puedes confiar en tus intuiciones como de costumbre, y (b) contemplar os instrumentos. En este caso os instrumentos son os usuarios. Cuando se diseña para otras personas tienes que ser empírico. Ya no puedes adivinar qué va a funcionar; tienes que descubrir usuarios y medir sus respuestas. Así que si vas a realizar algo para os adolescentes o os usuarios "comerciales" o determinado otro grupo que no te incluya, tienes que ser capaz de persuadir a algunos en particular a usar lo que estás haciendo. Si no puedes, estás en el sendero equivocado. Recabar Muy Escaso Dinero Las startups más exitosas cogen financiamiento en determinado momento. Al idéntico que tener más de un fundador, parece una buena apuesta estadísticamente. Sin embargo ¿cuánto se debe tomar? El financiamiento de una startup se mide en tiempo. Cada startup que no es rentable (es decir, casi todas ellas, en un principio) tiene una alguna porción de tiempo disponible antes de que se acabe el dinero y tengan que parar. A esto se le designa a veces como pista de aterrizaje, como en "¿Qué tanta pista te queda?" Es una buena metáfora, ya que te recuerda que cuando se acabe el dinero vas a estar en el aire o muerto. Muy escaso dinero implica no lo suficiente como para alzar el vuelo. Lo que alzar el vuelo implica depende de la situación. Por lo general, tienes que avanzar a un nivel visiblemente superior: si todo lo que tienes es una idea, un prototipo funcional; si tienes un prototipo, el lanzamiento; si ya lanzaste, un crecimiento implicativo. Depende de os inversionistas, ya que hasta que seas rentable, es a quien tienes que convencer. Así que si tomas dinero de os inversionistas, hay que tener lo suficiente para llegar al próximo paso, sea cual sea. Afortunadamente tienes determinado control tanto sobre lo que gastas como sobre cual es el próximo paso. Aconsejamos a las startups fijar ambos bajo, en un principio: gasta prácticamente nada, y haz que tu meta inicial sea simplemente crear un prototipo sólido. Esto te da la máxima flexibilidad. Gastar Demasiado Es difícil diferenciar el gastar demasiado del recabar muy poco. Si te quedas sin dinero, puedes decir que cualquiera de ellas fuese la causa. La única forma de determinar como llamarla es comparándolo con otras startups. Si recabaste cinco millones y te quedaste sin dinero, es posible que hayas gastado mucho. Gastar mucho dinero no es tan general como lo solía ser. Os fundadores parecen haber aprendido la lección. Además de que es cada vez más barato empezar una startup. Así que al momento de escribir esto muy pocas startups gastan demasiado. Ninguna de las que hemos financiado lo han hecho. (Y no sólo porque hacemos inversiones pequeñas; muchas han llegado a recabar nuevas rondas) La forma clásica de gastar mucho positivos es contratando mucha gente. Esta muerde por partida doble: asimismo de crecer tus costos, reduce tu velocidad?así que el dinero que se está consumiendo más veloz tiene que durar más tiempo. La mayoría de os hackers entienden por qué ocurre eso; Fred Brooks lo explica en The Mythical Man-Month Tenemos tres sugerencias globales sobre la empleación: (a) no lo hagas si puedes evitarlo, (b) págale a la gente con acciones y no con salario, no sólo para economizar dinero, sino porque deseas el tipo de personas que están lo suficientemente comprometidas para preferir eso, y (c) sólo emplea a personas que, o bien van a escribir código, o salir a obtener usuarios, porque esas son las únicas cosas que requieres al principio. Recabar Demasiado Dinero Es evidente cómo escaso dinero te puede matar, ¿pero hay tal cosa como tener demasiado? Sí y no. El asunto no es tanto el dinero en sí mismo como lo que viene con él. Como lo dijo un capitalista de riesgo que habló en Y Combinator Una vez que tomas varios millones de dólares de mi dinero, el reloj esta corriendo. " Si os capitalistas de riesgo te financian, no van a permitir que simplemente pongas el dinero en el banco y sigas operando como dos chicos que sobreviven comiendo sopas instantáneas. Elos desean que el dinero se ponga a trabajar. Por lo menos te mudaras a espacio de oficina correcto y contrataras más personas. Eso va a cambiar la atmósfera, y no del todo para bien. Ahora, la mayoría de tu gente serán funcionarios en espacio de fundadores. No estarán tan comprometidos; se les tendrá que decir qué hacer; empezaran a enfrascarse en políticas de oficina. Cuando recaudas una mayor porción de dinero, tu compañía se traslada a os suburbios y tiene hijos. Tal vez lo más peligroso: una vez que tomas mucho dinero se hace más difícil cambiar de dirección. Supongamos que tu plan inicial era vender algo a las empresas. Después de beber el dinero de os capitalistas de riesgo contratas a un equipo de ventas para realizar eso. ¿Qué pasa ahora si te das cuenta de que deberías estar haciendo esto para os consumidores en espacio de os negocios? Esa es un tipo de venta completamente diferente. Lo que sucede, en la práctica, es que no te das cuenta de eso. Cuanta más gente tengas, más te quedas apuntando en la misma dirección. Otro de os inconvenientes de las masivos inversiones es el tiempo que tardan. El tiempo indispensable para recabar dinero aumenta con la porción. Cuando la porción se eleva a varios millones, os inversionistas se ponen muy cauteosos. Las VCs jamás dicen sí o no; sino que sólo te involucran en una conversación aparentemente sin fin. Recaudar masivos porciónes de las VCs, es en consecuencia un enorme drenaje de tiempo? más, probablemente, que la particular startup. Y no quieres pasar todo tu tiempo hablando con os inversionistas, entretanto que tus competidores están pasando el suyo construyendo cosas. Aconsejamos a os fundadores que van a buscar dinero de capital riesgo beber la primera oferta razonable que reciben. Si recibes una oferta de una compañía de renombre con una valoración razonable, sin términos inusualmente onerosos, tómala y Seguid adelante con la creación de la compañía. ¿A quién le importa si pudierais llegar a un acuerdo un 30% mejor en otro lugar? Económicamente, las startups son un juego de todo o nada. Andar a la caza de gangas entre os inversionistas es una pérdida de tiempo. Mala Administración del Inversionista Como fundador, tienes que manejar a tus inversionistas. No debes ignoraros, porque pueden tener puntos de vista útiles. Pero tampoco debes dejaros administrar la empresa. Se supone que ese es tu trabajo. Si os inversionistas tenían la suficiente visión para administrar las compañías que financian, ¿por qué no las empezaron? Molestar a os inversionistas ignorándoos es, probablemente, menos peligroso que ceder ante eos. En vuestra startup, nos equivocamos por el lado de ignoraros. Una mayor porción de vuestra energía se dreno en disputas con os inversionistas en espacio de aplicarse en el artículo. Pero esto fuese menos costoso que ceder, lo que probablemente habría destruido la empresa. Si os fundadores saben lo que están haciendo, es mejor tener la mitad de su vigilancia centrada en el artículo que la vigilancia total de inversionistas que no saben. Qué tan duro tienes que laborar manejando a os inversionistas por lo común depende de la porción de dinero que habéis tomado. Cuando recaudas dinero a escala VC, os inversionistas consiguen una mayor porción de control. Si tienen una mayoría en el consejo de administración, son literalmente tus jefes. En el caso más común, donde os fundadores y os inversionistas están representados por idéntico y el voto decisivo es emitido por directores externos neutrales, todo lo que os inversionistas tienen que realizar es persuadir a os directores externos para controlar la compañía. Si las cosas van bien, esto no debería importar. Siempre y cuando parezcas estar progresando rápidamente, la mayoría de os inversionistas te dejarán en paz. Pero las cosas no siempre van bien en las startups. Os inversionistas han creado dificultades inclusive a las compañías más exitosas. Uno de os ejempos más célebres es el de Apple, cuyo consejo de administración cometió un yerro casi fatal despidiendo a Steve Jobs. Al parecer, inclusive Google recibió mucho castigo de sus inversionistas al principio. 15. S acrificar a os Usuarios (por Supuestas) Ganancias Cuando dije al comienzo que si haces algo que os usuarios quieren, te irá bien, habrás notado que no mencioné nada acerca de tener el modelo de negocios adecuado. Eso no es por que realizar dinero no sea importante. No estoy sugiriendo que os fundadores empiecen compañías sin ninguna probabilidad de ganar dinero con la esperanza de venderlas antes de que se estanquen. La razón por la que le manifestamos a os fundadores que no se preocupen al comienzo por el modelo de negocios es que realizar algo que la gente quiera es mucho más difícil. No sé por qué es tan difícil realizar algo que la gente quiera. Parece que debería ser sencillo. Pero se puede decir que debe ser difícil por la poca porción de startups que lo hacen. Debido a que realizar algo que la gente quiera es mucho más difícil que realizar dinero con ello, debes abandonar os modeos de negocios para más adelante, del mismo modo que abandonarías cierta característica trivial, pero confusa para la versión 2. En la versión 1, resuelve el asunto central. Y el asunto central en una startup es como crear riqueza (= la porción de gente que desea algo x el número que lo desean), y no cómo convertir esa riqueza en dinero. Las compañías que ganan son os que ponen a os usuarios en primer lugar. Google, por ejemplo. Eos hicieron que la búsqueda funcionara, luego, se preocuparon de cómo realizar dinero con ello. Y sin embargo, algunos fundadores de startups todavía creen que es irresponsable no enfocarse en el modelo de negocios desde el principio. A menudo son animados a ello por os inversionistas, cuya experiencia proviene de industrias menos maleables. Es irresponsable no pensar en modelos de negocio. Es sólo que es diez veces más irresponsable no pensar en el producto. No Desear Ensuciarse las Manos Casi todos os programadores eligen pasar su tiempo escribiendo código y tener a alguien que maneje el confuso tema de extraer dinero de ello. Y no sólo os perezosos. Larry y Sergey aparentemente se sintieron de esta forma también al principio. Después de construir su nuevo algoritmo de búsqueda, lo primero que intentaron fuese obtener que cierta otra compañía lo comprara. ¿Iniciar una empresa? ¡Ouch! La mayoría de os hackers eligen tan sólo tener ideas. Pero como Larry y Sergey descubrieron, no hay mucho mercado para las ideas. Nadie confía en una idea hasta que la incorporas en un artículo y lo utilizas para aumentar una fundamento de usuarios. Entonces te pagan a lo grande. Tal vez esto va a cambiar, pero dudo que vaya a cambiar mucho. No hay nada como os usuarios para persuadir a os compradores. No es sólo que el riesgo se reduce. Os compradores son humanos, y tienen problemas para pagar a un grupo de chicos millones de dólares sólo por ser inteligentes. Cuando la idea se materializa en una compañía con una mayor porción de usuarios, pueden decirse a sí mismos que están comprando os usuarios en espacio de la inteligencia, y para eos esto es más sencillo de digerir. Si vas a seducir a os usuarios, es posible que tengas que levantarte de tu computadora y vayas a buscar algunos. Es un esfuerzo desagradable, pero si puedes obligarte a realizarlo tienes muchas más probabilidades de éxito. En el primer grupo de startups que financiamos, en el verano de 2005, la mayoría de os fundadores invirtió todo su tiempo construyendo sus aplicaciones. Pero había una que estaba afuera la mitad del tiempo hablando con ejecutivos de compañías de telefonía celular, tratando de concertar acuerdos. ¿Puedes imaginar algo más doloroso para un hacker? Sin embargo valió la pena, ya que esta startup parece ser la más exitosa de ese grupo por un orden de magnitud. Si deseas empezar una startup, tienes que enfrentar el hecho de que no puedes sólo hackear. Por lo menos un hacker tendrá que pasar fracción del tiempo haciendo cosas de negocios. Disputas entre os Co-fundadores Las peleas entre os fundadores son sorprendentemente comunes. Alrededor del 20% de las startups que hemos financiado han tenido un fundador que abandona. Esto sucede tan a menudo que hemos revertido vuestra actitud frente a la adquisición de derechos. Todavía no la requerimos, pero ahora aconsejamos a os fundadores realizarlo para que haya una forma ordenada para que la gente se marche. Sin embargo, un fundador que se marcha no necesariamente mata a una startup. Le ha ocurrido a muchas startups. Afortunadamente, por lo común es el fundador menos comprometido el que se va. Si hay tres fundadores y uno que estaba tibio se va, mayor cosa. Si tienes dos y uno se va, o un tipo con habilidades técnicas apreciaciónes se va, eso es más un problema. Pero inclusive eso se puede sobrevivir. Blogger se quedo con una sola persona, y se recuperó. La mayoría de las disputas que he visto entre os fundadores podrían haberse evitado si hubieran tenido más cuidado sobre con quién fundaban la compañía. La mayoría de os conflictos no se deben a la situación, sino a las personas. Lo que implica que son inevitables. Y la mayoría de os fundadores que han sido quemados por estas disputas probablemente tenían dudas, que suprimieron, cuando iniciaron la compañía. No suprimas las dudas. Es mucho más sencillo solucionar os dificultades antes de que se inicie la compañía que después. Así que no incluyas a tu compañero de cuarto en tu startup sólo porque se sentiría excluido de lo contrario. No empieces una compañía con alguien que no te suena sólo porque tiene cierta habilidad que requieres y te inquieta no descubrir a nadie más. Las personas son el ingrediente más significativo en una startup, así que no hagas concesiones ahi. Un Esfuerzo a Medias Las startups fallidas de las que más escuchas son las que arden espectacularmente. Esas son en verdad la élite de las fallas. El tipo más general no es la que comete yerros espectaculares, sino la que no hace mucho de nada?aquella de la que ni siquiera oimos hablar, porque era un programa que un par de chicos comenzaron por un lado entretanto trabajaban en sus empleos diurnos, pero que jamás llegó a ninguna fracción y fuese abandonado escaso a escaso. Estadísticamente, si deseas eludir el fracaso, pareceria que la cosa más significativo es renunciar a tu manejo diurno. [a] La mayoría de os fundadores de startups fallidas no renunciaron a sus manejos diurnos, y la mayoría de las exitosas lo hicierón. Si el fracaso de una startup afuera enfermedad, el CDC [b] estaria emitiendo boletines de alerta a la gente para eludir os manejos diurnos. ¿Eso implica que debes renunciar a tu trabajo? No necesariamente. Estoy suponiendo aquí, pero me imagino que muchos de estos potenciales fundadores pueden no tener la clase de determinación necesaria para empezar una empresa, y que en el fondo de sus mentes, lo saben. La razón por la que no invierten más tiempo en su startup es que saben que es una mala inversión. Supongo también que hay un grupo de gente que podría haberlo logrado si hubieran dado el salto y lo hubieran hecho a tiempo completo, pero no lo hicieron. No poseo idea de qué tan amplio es este grupo, pero si la progresión ganador/casi/sin oportunidad tiene el tipo de distribución que es de esperar, el número de personas que podría haberlo hecho, si hubieran dejado su empleo, es probablemente un orden de magnitud gran que el número de os que lo hacen. Si eso es cierto, la mayoría de las startups que podrían tener éxito fallan porque os fundadores no dedican todo su trabajo a ellas. Lo que verdaderamente concuerda con lo que veo en la realidad. La mayoría de las startups fracasan porque no hacen algo que la gente quiere, y la razón por la que no lo hacen es que no se esfuerzan lo suficiente. En otras palabras, empezar startups es idéntico que todo lo demás. El gran yerro que puedes cometer es no tratar lo suficiente. En la medida en que hay un secreto para el éxito, es no estar en negación acerca de eso.

java development, MouseGrid de Dragon Naturally Speaking

Dragon Naturally Speaking es un software de reconocimiento de voz que ya tiene bastantes años. Lo desarrolla una compañía llamada Nuance. El reconocimiento de voz aún no está a la altura de lo que uno podría esperar... pero ha mejorado mucho bastante hace años. Ya no hace falta entrenar al sistema mientras algúnas horas, aunque sí que requiere un entrenamiento anterior de varios minutos. Dragon es usado por muchas personas con dificultades motores o de movilidad para utilizar el ordenador, ya que faculta manejar el ordenador simplemente con la voz. Una alternativa muy interesante que posee es MouseGrid. La podemos en la página 61 de la guía del usuario de Dragon Naturally Speaking (versión 11). Esta tecnología faculta situar el cursor del ratón en cualquier fracción de la pantalla mediante unos comandos de voz. Para ello se tiene que activar la alternativa "Dividir pantalla", que retrata una cuadrícula sobre la pantalla. También se puede decir "Dividir ventana" para situar la cuadrícula sobre la ventana activa. Al decir un número del 1 al 9 se coloca el cursor en el área numerada. Por ejemplo, en la imagen anterior, para activar la "Papelera de reciclaje", primero habría que decir "4". A continuación, el área de pantalla seleccionada se divide en una cuadrícula más pequeña. Ahora, para activar la "Papelera de reciclaje" habría que regresar a decir "4". Este proceso se puede repetir tantas veces como haga falta hasta que el cursor del ratón se sitúa sobre un icono, un botón, un enlace u otro objeto similar. Una vez ubicado el cursor del ratón, se puede realizar clic, doble clic, botón derecho, arrastrar, etc

java development, Obtener mensajes de WhatsApp

Hace escaso me compré un celular para reemplazar mi palm treo 650 que paso a otra vida, traté de buscar uno que me permitiera tener las mismas ventajas que mi palm y que esté a un buen precio. Lo que mas me interesaba era la instalacion de aplicaciones y wifi, que hoy en dia cualquier smartphone posee. El SO por conveniencia era el Android, así que con mi Motorola XT720 en mis manos comencé a instalar y probar distintos aplicaciones. Algo que me llamó mucha la vigilancia fuese que, antes de descargar una aplicación nos piden aceptar una serie de cláusulas que la aplicación en tangible puede hacer en vuestro equipo, ejemplo: Herramientas del sistema: -Impedir que el teléfono entre en modo de suspención, leer ficheros del registro, reiniciar otras aplicaciones etc. Comunicación de red: -En el caso que haya, entrada a internet, crear conexiones. etc Almacenamiento: -Leer, Modificar y descartar contenido de la tarjeta. Llamadas de teléfono: -Leer la identidad y el estado del teléfono. Y Así un largo etc, todo depende de la aplicación a instalar. Una aplicación que me pareció muy util fuese Android Terminal Emulator, como sabía que Android era un kernel modificado de linux creí que resultaría bastante útil. Luego decidí instalar WhatsApp, esa aplicación tan popular para experimentar un poco. Una vez instalado, comencé a probarlo y me surgió una duda: ¿Será probable alcanzar a las conversaciones? Para esto hay que ver como se almacena los datos, al parecer WhatsApp crea una pequeña fundamento de datos que almacena en el Sistema Operativo. El tipo de fundamento de datos es local, por lo que emplea SQLite. Como ya había hecho algúnas aplicaciones antes en Java y C# con este tipo de fundamento de datos, no me resultaba nada de otro mundo. Para los que no saben, SQLite es un pseudomotor de fundamento de datos, esto porque no se requiere de un servidor y muestra una mejor manera de Guardar datos locales de una aplicación que hagamos. En el caso de WhatsApp emplea dos ficheros msgstore.d wa.db. El primero para los mensajes y el otro para los contactos. Ahora con la aplicación Android Terminal Emulator solo hay que buscar y transferir estos archivos, que no son mas que comandos de linux. Primero ejecutamos para tener permisos de superusuarios, después find -name msgstore.db para saber la ruta exacta donde se encontraba. cd sdcard desde el directorio raíz para entrar a la tarjeta de memoria y copiamos el ficheros con cp ruta msg.db Lo demás solo lo puse para presentar los datos del directorio. Ahora con la fundamento de datos en la memoria, conectamos el teléfono móvil al PC. Para poder ver el contenido de la fundamento de datos simplemente voy a utilizar un complemento de FireFox que ya tenía instalado. El SQLite Manager lo pueden descargar entrando a Herramientas/Complementos y buscarlo o directamente de https://addons.mozilla.org/en-US/firefox/addon/sqlite-manager/ Una vez instalado, abriendo FireFox en el menú Herramientas vamos a SQLite Manager Y se nos abrirá otra ventana en la que solo poseemos que abrir y buscar el archivo que guardamos. Haciendo click en la tabla "Messages" aparecerá la lista con los mensajes, los destinatarios e inclusive en algunos casos en que se utilice, la posición geográfica. Como ven, hay que tener mucho cuidado con las aplicaciones que se utilizan. No vaya a ser que alguien esté viendo tus conversaciones Actualizacion (18/06/12): Para fundamento de datos encriptadas vean la próximo acceso ;) ACTUALIZACIÓN: (22/01/13) difícil interpretación, desencriptadas ) Que agrupa los mensajes por conversaciones a un algun usuario y traduce las fechas a un formato legible. Almacenando todo en un archivo de texto: 1-Copiar el archivo msg.db generado por el WhatsAppDecrypt a la carpeta del WhatsAppLogExtractor. 2-Ejecutar el WhatsAppLogExtractor.jar . Se generará un archivo de texto llamado fichero.txt. 3-Abrir el fichero generado.

java development, OPERADORES

- Instrucciones simples de impresión - Utilización de los operadores Java - Precedencia - Asignación - Creación de alias en las llamadas a métodos - Operadores matemáticos - Operadores unarios mas y menos - Autoincremento y autodecremento - Operadores relacionales - Comprobación de la equivalencia de objetos - Operadores lógicos - Cortocircuitos - Literales - Notación exponencial - Operadores bit a bit - Operadores de desplazamiento - Operador ternario if - else - Operadores + y += para String - Yerros comunes a la hora de utilizar operadores - Operadores de proyección - Truncamiento y redondeo - Promoción - Java no tiene operador "sizeof" - Compendio de operadores En el nivel inferior, los datos en Java se manipulan utilizando operadores. INSTRUCCIONES SIMPLES DE IMPRESIÓN Si nos fijamos en la próximo instrucción System.out.println("Un montón de texto que escribir"); Es una instrucción bastante larga y que se reitera mucho, por lo que el autor de este libro crea una biblioteca para simplificar la escritura de las instrucciones de impresión. Para poder utilizar esta biblioteca hay que descargarla de www.mindview.net, descomprimir el árbol de código y agregar el directorio raíz de dicho árbol de código a la variable de ámbito CLASSPATH. Un ejemplo del uso de esa biblioteca es: //: operators/HelloDate.java import java.util.*; import static net.mindview.util.Print.*; public class HelloDate { public static void main(String[] args) { print("Hello, it's: "); print(new Date()); /* Output: (55% match) Hello, it's: Wed Oct 05 14:39:05 MDT 2005 *///:~ En este ejemplo se emplea la instrucción print en espacio de System.out.println. Esto es así porque estamos empleando la biblioteca que importamos mediante: import static net.mindview.util.Print.*; Observa que se emplea static. Sin embargo, aunque se simplifican bastante los programas, si las instrucciones de impresión son pocas, es preferible seguir utilizando la manera habitual System.out.println en espacio de importar la biblioteca. Personalmente yo no he descargado la biblioteca y en los ejercicios voy a utilizar la manera larga para imprimir. Ejercicio 1. Escriba un proyecto que emplee tanto la manera "corta" como la usual de la instrucción de impresión. UTILIZACIÓN DE LOS OPERADORES JAVA En Java poseemos los operadores para: la suma, el operador más unario (+), la resta y el operador menos unario (-), la multiplicación (*), la división (/) y la asignación (=) y funcionan de forma parecida a otros lenguajes de programación. Un operador coge uno o más argumentos y genera un nuevo valor. Los operadores producen un valor a dividir de sus operandos. Además, algunos operadores varían el valor del operando, produciendo lo que se llama resultado colateral, por ejemplo, ++, --. Casi todos los operadores funcionan únicamente con primitivas excepto '=', '==' y '!=' que funcionan con todos los objetos. String también soporta '+' y '+='. PRECEDENCIA La precedencia es el orden en el que se evalúa una expresión cuando hay varios operadores. En Java hay unas normas que definen el orden de evaluación. La multiplicación y la división se realizan antes que la suma y la resta. El resto de normas suelen olvidarse, así pues se emplean paréntesis para establecer el orden en el que se ha de valorar una expresión. En el ejemplo: //: operators/Precedence.java public class Precedence { public static void main(String[] args) { int x = 1, y = 2, z = 3; int a = x + y - 2/2 + z; // (1) int b = x + (y - 2)/(2 + z); // (2) System.out.println("a = " + a + " b = " + b); /* Output: a = 5 b = 1 *///:~ Si nos fijamos el fruto para a y b es distinto sin paréntesis y con paréntesis. La expresión System.out.println() incluye el operador +, en este caso se emplea para concatenar cadenas de caracteres. Cuando el compilador ve un objeto String seguido de '+' intenta convertirlo a un objeto String. En este caso convierte un int a String para a y b. ASIGNACIÓN La asignación se realiza con el operador =. Su significado es: coge el valor del lado derecho (rvalor) y cópialo en el lado izquierdo (lvalor). Un rvalor es cualquier constante, variable o expresión que genere un valor. Un lvalor es una variable determinada, designada mediante su nombre, debe haber un lugar físico para Guardar su valor. Podemos asignar un valor constante a una variable: a=4; Pero no podemos asignar nada a un valor constante, ya que una constante no puede ser un lvalor. 4=a; La asignación de primitivas es sencilla. La primitiva almacena el valor real y no una referencia a cualquier objeto, cuando se asignan primitivas se asigna el contenido de un espacio a otro. Si poseemos a=b, el contenido de b se copia en a, si modificamos a, el valor de b no cambia. Esto es lo lógico. Pero con los objetos la cosa cambia. Cuando manipulamos objetos en verdad estamos manipulando la referencia. Es decir, si poseemos la expresión c=d, tendremos a los objetos c y d apuntando a la misma referencia, al objeto al que sólo apuntaba d originalmente. Vamos a ver un ejemplo: //: operators/Assignment.java // Assignment with objects is a bit tricky. import static net.mindview.util.Print.*; class Tank { int level; public class Assignment { public static void main(String[] args) { Tank t1 = new Tank(); Tank t2 = new Tank(); t1.level = 9; t2.level = 47; print("1: t1.level: " + t1.level + ", t2.level: " + t2.level); t1 = t2; print("2: t1.level: " + t1.level + ", t2.level: " + t2.level); t1.level = 27; print("3: t1.level: " + t1.level + ", t2.level: " + t2.level); /* Output: 1: t1.level: 9, t2.level: 47 2: t1.level: 47, t2.level: 47 3: t1.level: 27, t2.level: 27 *///:~ Tenemos una clase Tank con un único tema level de tipo int. En la clase Assignment se crean dos objetos y dos instancias de la clase Tank, a cada tema level se le da un valor. Cuando se asigna t1=t2, t1.level y t2.level apuntan a la misma referencia y la referencia a la que apuntaba t1 se pierde, posteriormente será eliminada por el recolector de basura. Cuando se varía t1.level=27 se podría pensar que t2.level=47, sin embargo esto no es así, t1.level=27 y t2.level=27, ya que ambos objetos apuntan a la misma referencia, por tanto, si varíamos uno de ellos varíamos otro. Esto se llama creación de alias. ¿Qué hacemos si no deseamos que las dos referencias apunten al mismo objeto? Podemos realizar la asignación a otro nivel: t1.level=t2.level; Así se mantienen independientes los dos objetos. Aunque en verdad esto resulta bastante confuso y va en contra de los comienzos de un buen diseño orientado a objetos. Ejercicio 2. Cree una clase que contenga un valor float y utilícela para ilustrar el fenómeno de la creación de alias. Creación de alias en las llamadas a métodos La creación de alias también se manifiesta cuando se pasa un objeto a un método: //: operators/PassObject.java // Passing objects to methods may not be // what you're used to. import static net.mindview.util.Print.*; class Letter { char c; public class PassObject { static void f(Letter y) { y.c = 'z'; public static void main(String[] args) { Letter x = new Letter(); x.c = 'a'; print("1: x.c: " + x.c); f(x); print("2: x.c: " + x.c); /* Output: 1: x.c: a 2: x.c: z *///:~ En otros lenguajes de programación, el método f(Letter y) haría una copia del argumento Letter dentro del entorno del método, pero aquí se pasa una referencia, por tanto, la línea: y.c='z'; varía el objeto que está afuera de f(Letter y). La creación de alias y su solución es un asunto complejo, hay que tenerlo en cuenta para detectar probables errores. Ejercicio 3. Cree una clase que contenga un valor float y utilícela para ilustrar el fenómeno de la creación de alias mientras las llamadas a métodos. OPERADORES MATEMÁTICOS Los operadores matemáticos básicos son: suma(+), resta(-), multiplicación(*), división(/) y módulo(%) que es el resto de una división entera. La división entera trunca en espacio de redondear. Java también emplea la notación resumida que realiza una operación y una asignación al mismo tiempo. Se denota mediante un operador (+, -, *, /, %) seguido de un signo idéntico y se puede emplear con todos los operadores allí donde tenga sentido. Por ejemplo, x+=4, sumaría 4 a la variable x y se asignaría el fruto a x. Veamos un ejemplo del uso de operadores matemáticos: //: operators/MathOps.java // Demonstrates the mathematical operators. import java.util.*; import static net.mindview.util.Print.*; public class MathOps { public static void main(String[] args) { // Create a seeded random number generator: Random rand = new Random(47); int i, j, k; // Choose value from 1 to 100: j = rand.nextInt(100) + 1; print("j : " + j); k = rand.nextInt(100) + 1; print("k : " + k); i = j + k; print("j + k : " + i); i = j - k; print("j - k : " + i); i = k / j; print("k / j : " + i); i = k * j; print("k * j : " + i); i = k % j; print("k % j : " + i); j %= k; print("j %= k : " + j); // Floating-point number tests: float u, v, w; // Applies to doubles, too v = rand.nextFloat(); print("v : " + v); w = rand.nextFloat(); print("w : " + w); u = v + w; print("v + w : " + u); u = v - w; print("v - w : " + u); u = v * w; print("v * w : " + u); u = v / w; print("v / w : " + u); // The following also works for char, // byte, short, int, long, and double: u += v; print("u += v : " + u); u -= v; print("u -= v : " + u); u *= v; print("u *= v : " + u); u /= v; print("u /= v : " + u); /* Output: j : 59 k : 56 j + k : 115 j - k : 3 k / j : 0 k * j : 3304 k % j : 56 j %= k : 3 v : 0.5309454 w : 0.0534122 v + w : 0.5843576 v - w : 0.47753322 v * w : 0.028358962 v / w : 9.940527 u += v : 10.471473 u -= v : 9.940527 u *= v : 5.2778773 u /= v : 9.940527 *///:~ En este ejemplo se crea un objeto Random. Si se crea sin ningún argumento, Java usa la hora actual como semilla para generar números aleatorios y esto generaría una salida distinto en cada ejecución del programa. Para que la salida que se presenta al final de cada ejemplo sea lo más coherente posible, se ofrece una semilla (valor de inicialización para el generador de números aleatorios que siempre genera la misma salida para alguna semilla), al crear el objeto Random (Random rand = new Random(47);) siempre se generarán los mismos números aleatorios, así se podrá verificar la salida del ejemplo. Se generan varios números aleatorios con el objeto Random simplemente invocando los métodos nextInt() y nextFloat(), también se pueden invocar nextLong() o nextDouble(). El argumento de nextInt() constituye la cota sobresaliente para el número generado. La cota inferior es cero, lo cual no es deseable debido a la probabilidad de división por 0, por eso se suma uno al resultado. Ejercicio 4. Escriba un proyecto que calcule la velocidad utilizando una distancia constante y un tiempo constante. Operadores unarios más y menos El menos unario (-) y el más unario (+), son los mismos operadores que para la suma y la resta. El menos unario invierte el signo de los datos y el más unario ofrece una simetría con respecto al más unario, pero no tiene ningún efecto. Algunos ejemplos: x=a*(-b); Los paréntesis se ponen por claridad. x=-a; Autoincremento y autodecremento En Java tienen lugar una serie de abreviaturas para facilitar la escritura de código. Los operadores de aumento y decremento son dos de ellas. El operador de aumento (++) crece en una unidad una variable (a++) y el de decremento (--) disminuye en una unidad la variable (a--). Hay dos versiones de cada tipo de operador, llamadas prefija y postfija. 1. Prefija. Los operadores ++ y -- surgen antes de la variable, (++a o --a). En este caso primero se realiza la operación y despues se genera el valor. 2. Postfija. Los operadores ++ y -- surgen después de la variable, (a++ o a--). En este caso se genera primero el valor y después se realiza la operación. Lo vemos con un ejemplo: //: operators/AutoInc.java // Demonstrates the ++ and -- operators. import static net.mindview.util.Print.*; public class AutoInc { public static void main(String[] args) { int i = 1; print("i : " + i); print("++i : " + ++i); // Pre-increment print("i++ : " + i++); // Post-increment print("i : " + i); print("--i : " + --i); // Pre-decrement print("i-- : " + i--); // Post-decrement print("i : " + i); /* Output: i : 1 ++i : 2 i++ : 2 i : 3 --i : 2 i-- : 2 i : 1 *///:~ Estos son junto la asignación, los únicos operadores con efectos colaterales. Modifican el operando en espacio de utilizar su valor. OPERADORES RELACIONALES Los operadores relacionales generan un fruto de tipo boolean. Evalúan la relación existente entre los operandos, si la relación es alguna el fruto es true, en caso opuesto es false. Los operadores relacionales son: - Menor que: (). - Mayor que: (>). - Menor o idéntico que: (=). - Mayor o idéntico que: (>=). - Equivalente o igual: (==). - No equivalente o diferente: (!=). La equivalencia y no equivalencia funcionan con todas las primitivas, sin embargo, los otros operadores relacionales no funcionan con el tipo boolean ya que no tiene sentido. Comprobación de la equivalencia de objetos Los operadores relacionales == y != funcionan con todos los objetos, pero su significado puede confundir a los que comienzan a programar en Java. Veamos un ejemplo: //: operators/Equivalence.java public class Equivalence { public static void main(String[] args) { Integer n1 = new Integer(47); Integer n2 = new Integer(47); System.out.println(n1 == n2); System.out.println(n1 != n2); /* Output: false true *///:~ Si nos fijamos en System.out.println(n1==n2), podríamos pensar que el fruto es true y false en System.out.println(n1!=n2), sin embargo, esto no es así ya que aunque el contenido de los objetos es el mismo, las referencias no son iguales, digamos que cada objeto apunta a una referencia diferente. Estos operadores comparan referencias a objetos, por lo que la salida es false y despues true. ¿Cómo podemos saber si el contenido de los objetos es equivalente? Mediante un método especial equals(), disponible para todos los objetos, no para las primitivas. Veamos el próximo ejemplo: //: operators/EqualsMethod.java public class EqualsMethod { public static void main(String[] args) { Integer n1 = new Integer(47); Integer n2 = new Integer(47); System.out.println(n1.equals(n2)); /* Output: true *///:~ El fruto es el que esperábamos. Sin embargo, la cosa no es tan sencilla, observa: //: operators/EqualsMethod2.java // Default equals() does not compare contents. class Value { int i; public class EqualsMethod2 { public static void main(String[] args) { Value v1 = new Value(); Value v2 = new Value(); v1.i = v2.i = 100; System.out.println(v1.equals(v2)); /* Output: false *///:~ El fruto es false. Esto es debido a que el comportamiento predeterminado de equals() consiste en comparar referencias. Obtendríamos el comportamiento esperado si sustituimos equals() en vuestra nueva clase. Pero hasta más adelante no vamos a ver la sustitución de unos métodos por otros y la manera apropiada de definir equals(). Sin embargo, el comportamiento de equal() nos va a economizar determinado que otro quebradero de cabeza. La mayoría de las clases de biblioteca Java implementan equals() de modo que compare el contenido de los objetos en espacio de sus referencias. Ejercicio 5. Cree una clase denominada Dog (perro) que contenga dos objetos String: name (nombre) y says (ladrido). En main(), cree dos objetos perro con los nombres Spot (que ladre diciendo "Ruff!") y Scruffy (que ladre diciendo "Wurf!"). Después, muestre sus nombres y el sonido que hacen al ladrar. Ejercicio 6. Continuando con el Ejercicio 5, cree una nueva referencia Dog y asígnela al objeto de nombre Spot. Realice una comparación utilizando == y equals() para todas las referencias. OPERADORES LÓGICOS Los operadores lógicos son AND (&&), OR (||) y NOT (!). Según la relación lógica de los operandos el fruto será idéntico a true o false. - AND. Si todos los operandos son verdaderos el fruto es true, si un operando o más es falso el fruto es false. - OR. Si un operando o más es verdadero el fruto es true, si todos los operandos son falsos el fruto es false. - NOT. Si un operando es true NOT lo transforma en false, si es false lo transforma en true, pero el valor del operando no varía, varía sólo en la relación lógica. //: operators/Bool.java // Relational and logical operators. import java.util.*; import static net.mindview.util.Print.*; public class Bool { public static void main(String[] args) { Random rand = new Random(47); int i = rand.nextInt(100); int j = rand.nextInt(100); print("i = " + i); print("j = " + j); print("i > j is " + (i > j)); print("i j is " + (i j)); print("i >= j is " + (i >= j)); print("i = j is " + (i = j)); print("i == j is " + (i == j)); print("i != j is " + (i != j)); // Treating an int as a boolean is not legal Java: //! print("i && j is " + (i && j)); //! print("i || j is " + (i || j)); //! print("!i is " + !i); print("(i 10) && (j 10) is " + ((i 10) && (j 10)) ); print("(i 10) || (j 10) is " + ((i 10) || (j 10)) ); /* Output: i = 58 j = 55 i > j is true i j is false i >= j is true i = j is false i == j is false i != j is true (i 10) && (j 10) is false (i 10) || (j 10) is false *///:~ Observa que se ha ya que entre comentarios (//!) i&&j, i||j y !i, esto es así porque los operadores relacionales sólo se pueden aplicar a valores de tipo boolean. En una expresión lógica no se puede contratar un valor que no sea booleano. El comentario (//!) faculta la eliminación automática de comentarios para facilitar las pruebas. Podemos ver que un valor boolean se convierte automáticamente a una manera de tipo texto adecuada cuando se usa en espacios donde lo que se aguarda es un valor de tipo String. En este último ejemplo se pueden reemplazar los valores int por cualquier otro tipo de dato primitivo excepto boolean. Si se trata de números en coma flotante, es difícil que dos números sean iguales ya que si los valores difieren en un único número ya son diferentes y cualquier número ubicado por arriba de cero por muy chico que sea Seguid siendo diferente de cero. Ejercicio 7. Escriba un proyecto que simule el proceso de arrojar una moneda al aire. Cortocircuitos Al tratar con operadores lógicos, nos encontramos con el fenómeno de los cortocircuitos. Cuando poseemos una expresión lógica, ésta se evalúa hasta que la veracidad o falsedad de la expresión es alguna de manera no ambigua, por tanto, fracciónes de la expresión lógica puede que no lleguen a evaluarse. Veamos un ejemplo: //: operators/ShortCircuit.java // Demonstrates short-circuiting behavior // with logical operators. import static net.mindview.util.Print.*; public class ShortCircuit { static boolean test1(int val) { print("test1(" + val + ")"); print("result: " + (val 1)); return val 1; static boolean test2(int val) { print("test2(" + val + ")"); print("result: " + (val 2)); return val 2; static boolean test3(int val) { print("test3(" + val + ")"); print("result: " + (val 3)); return val 3; public static void main(String[] args) { boolean b = test1(0) && test2(2) && test3(2); print("expression is " + b); /* Output: test1(0) result: true test2(2) result: false expression is false *///:~ En esta clase poseemos tres métodos test1, test2 y test3 que nos devuelven true o false dependiendo de si el valor que se introduce como argumento es gran que 1, 2 y 3 respectivamente. En main poseemos una variable b booleana que es el fruto de la expresión: test1(0) && test2(2) && test3(2), como el método test2(2) devuelve false, ni siquiera entramos al método test3(2) ya que sea cual sea el valor devuelto por este método la expresión va a ser false porque test2(2) ya ha devuelto false. De esta manera se mejora la velocidad del proyecto ya que no es indispensable valorar todas las fracciónes de una expresión lógica. Literales Cuando insertamos un valor literal en un programa, el compilador sabe qué tipo asignarle. A veces puede que este tipo sea ambiguo. Cuando esto ocurre, hay que guiar al compilador añadiendo alguna inmaneración adicional en manera de caracteres afiliados al valor literal. Veamos un ejemplo: //: operators/Literals.java import static net.mindview.util.Print.*; public class Literals { public static void main(String[] args) { int i1 = 0x2f; // Hexadecimal (lowercase) print("i1: " + Integer.toBinaryString(i1)); int i2 = 0X2F; // Hexadecimal (uppercase) print("i2: " + Integer.toBinaryString(i2)); int i3 = 0177; // Octal (leading zero) print("i3: " + Integer.toBinaryString(i3)); char c = 0xffff; // max char hex value print("c: " + Integer.toBinaryString(c)); byte b = 0x7f; // max byte hex value print("b: " + Integer.toBinaryString(b)); short s = 0x7fff; // max short hex value print("s: " + Integer.toBinaryString(s)); long n1 = 200L; // long suffix long n2 = 200l; // long suffix (but can be confusing) long n3 = 200; float f1 = 1; float f2 = 1F; // float suffix float f3 = 1f; // float suffix double d1 = 1d; // double suffix double d2 = 1D; // double suffix // (Hex and Octal also work with long) /* Output: i1: 101111 i2: 101111 i3: 1111111 c: 1111111111111111 b: 1111111 s: 111111111111111 *///:~ Un carácter ubicado al final de un valor literal faculta establecer su tipo. La L mayúscula o minúscula implica long (la minúscula suele ser confusa). Una F mayúscula o minúscula implica float. Una D mayúscula o minúscula implica double. Los valores hexadecimales (base 16), que funcionan con todos los tipos de datos enteros, van antecedidos de 0x o 0X seguido de 0-9 o a-f en mayúscula o minúscula. En el ejemplo previo se ve el valor máximo para char, byte y short. Si nos excedemos del valor máximo que estos tipos pueden contener, el compilador transformará automáticamente el valor a int y nos dirá que necesitamos una proyección hacia bajo (esto lo veremos un poco más adelante en este tema). Así sabremos que nos hemos pasado del límite permitido. Los valores octales (base 8) van antecedidos de un 0 y utilizando sólo los dígitos 0-7. Aunque no tiene lugar una representación literal para los números binarios en Java, a veces resulta provechoso presentar la manera binaria de los resultados. Esto lo podemos realizar con los métodos static toBinaryString() de las clases Integer y Long.Cuando se pasan tipos más pequeños a Integer.toBinaryString(), el tipo se convierte automáticamente a int. Ejercicio 8. Demuestre que las notaciones hexadecimal y octal funcionan con los valores long. Utilice Long.toBinaryString() para presentar los resultados. Notación exponencial Vamos a ver un ejemplo de notación exponencial: //: operators/Exponents.java // " e="" means="" 10="" to="" the=" public class Exponents { public static void main(String[] args) { // Uppercase and lowercase 'e' are the same: float expFloat = 1.39e-43f; expFloat = 1.39E-43f; System.out.println(expFloat); double expDouble = 47e47d; // 'd' is optional double expDouble2 = 47e47; // Automatically double System.out.println(expDouble); /* Output: 1.39E-43 4.7E48 *///:~ En el tema de las ciencias y la ingeniería, 'e' hace referencia a la fundamento de los logaritmos naturales, que es aproximadamente 2,718 (en Java hay un 'e' double más preciso, Math.E). Esto se usa en expresiones de exponenciación, así 1,39*e-43 es 1,39*2,718e-43. Sin embargo, cuando se inventó FORTRAN se decidió que 'e' significaría "diez elevado a", lo cual es bastante raro pero este valor ha ido pasando a C, C++ y Java, por tanto, 1,39e-43f es 1,39*10e-43. No es indispensable utilizar el carácter sufijo cuando el compilador puede deducir el tipo apropiado. Así: long n3=200; Aquí no hay ambigüedad, por lo que no es indispensable colocar la L después de 200. Sin embargo en: float f4=1e-43f; // 10 elevado a el compilador estima los números exponenciales como double, por tanto, si no ponemos la f final nos daría un yerro en el que nos indicaría que hay que usar una proyección para convertir el valor double a float. Ejercicio 9. Visualice los números más grande y más chico que se pueden representar con la notación exponencial en el tipo float y en el tipo double. Operadores bit a bit Los operadores bit a bit facultan manipular bits individuales en un tipo de datos entero primitivo. Para conseguir el fruto se realizan operaciones de álgebra booleana con los bits correspondientes de los dos argumentos. Estos operadores usualmente no los utilizaremos mucho en vuestros programas. Vamos a ver los operadores bit a bit que tenemos: - AND (&). Genera un 1 si los dos bits de acceso son 1, en caso opuesto genera un 0. - OR (|). Genera un 1 si sdeterminados de los bits de acceso es un 1, si los dos bits de acceso son 0 genera un 0. - EXCLUSIVE OR o XOR (^). Genera un 1 si uno de los dos bits de entrada, pero no ambos, es 1, en caso opuesto genera un cero. - NOT (~). Es un operador unario que sólo admite un argumento. Genera un 1 si el bit de acceso es 0 y un 0 si el bit de acceso es 1, es decir el contrario al bit de acceso. Los operadores bit a bit y los lógicos emplean los mismos símbolos para sus operaciones. Un truco para recordar cuál hay que utilizar para cada operación es: como los bits son pequeños para las operaciones bit a bit utilizamos sólo un símbolo y para las lógicas dos. Los operadores bit a bit pueden combinarse con el símbolo igual: &=, |= y ^=. El tipo boolean es distinto a los otros tipos primitivos pues se trata como un valor de un único bit. Se puede hacer una operación AND, OR y XOR bit a bit, pero no una operación NOT. Para los valores booleanos, los operadores bit a bit tienen el mismo resultado que los operadores lógicos, excepto que no se aplica la norma del cortocircuito. Además las operaciones bit a bit incluyen al operador lógico XOR, que no manera fracción de los operadores lógicos. Ejercicio 10. Escribe un proyecto con dos valores persistentes, uno en el que haya unos y ceros binarios alternados, con un cero en el dígito menos importante, y el segundo con un valor también alternado pero con un uno en el dígito menos importante (consejo: lo mas sencillo es usar persistentes hexadecimales para esto). Tome estos dos valores y combínelos de todas las maneras probables utilizando los operadores bit a bit, y visualice los frutos utilizando Integer.toBinaryString(). Operadores de desplazamiento Los operadores de desplazamiento también sirven para manipular bits. Sólo se pueden utilizar con tipos primitivos enteros. Los operadores de desplazamiento son: - Operador de desplazamiento a la izquierda (). Genera como fruto el operando ubicado a la izquierda del operador después de desplazarlo hacia la izquierda el número de bits especificado a la derecha del operador (insertando 0 en los bits de menor peso). - Operador de desplazamiento a la derecha con signo (>>). Genera como fruto el operando ubicado a la izquierda del operador después de desplazarlo hacia la derecha el número de bits especificado a la derecha del operador. Además emplea lo que se llama expansión de signo: si el valor es efectivo se insertan 0 en los bits de gran peso, si es negativo se insertan 1 en los bits de gran peso. - Operador desplazamiento a la derecha sin signo (>>>). Emplea lo que se designa expansión con ceros, independientemente del signo, se insertan 0 en los bits de gran peso. Si se desplaza un valor de tipo char, byte o short, será convertido a int antes de que el desplazamiento tenga espacio y el fruto será de tipo int. Sólo se utilizarán los bits de menor peso del lado derecho, esto evita que se realicen desplazamientos con un número de posiciones sobresaliente al número de bits de un valor int. Si poseemos un valor long, se obtendrá un fruto de tipo long y sólo se emplearán los seis bits de menor peso del lado derecho, para así no desplazar más posiciones que el número de bits de un valor long. Los desplazamientos se pueden combinar con el signo igual: = o >>= o >>>=. El lvalor se sustituye por el lvalor desplazado de acuerdo con lo que marque el rvalor. Existe un asunto con el desplazamiento a la derecha sin signo combinado con la asignación. Si se usa con valores de tipo byte o short, no se obtienen los frutos correctos. En espacio de ello se transforman a int y despues se desplazan a la derecha, pero a continuación se truncan al regresar a asignar los valores a sus variables, por lo que se obtiene -1 en esos casos. Vamos a verlo con un ejemplo: //: operators/URShift.java // Test of unsigned right shift. import static net.mindview.util.Print.*; public class URShift { public static void main(String[] args) { int i = -1; print(Integer.toBinaryString(i)); i >>>= 10; print(Integer.toBinaryString(i)); long l = -1; print(Long.toBinaryString(l)); l >>>= 10; print(Long.toBinaryString(l)); short s = -1; print(Integer.toBinaryString(s)); s >>>= 10; print(Integer.toBinaryString(s)); byte b = -1; print(Integer.toBinaryString(b)); b >>>= 10; print(Integer.toBinaryString(b)); b = -1; print(Integer.toBinaryString(b)); print(Integer.toBinaryString(b>>>10)); /* Output: 11111111111111111111111111111111 1111111111111111111111 1111111111111111111111111111111111111111111111111111111111111111 111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111 11111111111111111111111111111111 11111111111111111111111111111111 11111111111111111111111111111111 11111111111111111111111111111111 1111111111111111111111 *///:~ En el último desplazamiento, el valor resultante no se asigna de nuevo a b, sino que se imprime directamente obteniéndose el comportamiento deseado. Vamos a ver un ejemplo con todos los operadores para el empleo de bits: //: operators/BitManipulation.java // Using the bitwise operators. import java.util.*; import static net.mindview.util.Print.*; public class BitManipulation { public static void main(String[] args) { Random rand = new Random(47); int i = rand.nextInt(); int j = rand.nextInt(); printBinaryInt("-1", -1); printBinaryInt("+1", +1); int maxpos = 2147483647; printBinaryInt("maxpos", maxpos); int maxneg = -2147483648; printBinaryInt("maxneg", maxneg); printBinaryInt("i", i); printBinaryInt("~i", ~i); printBinaryInt("-i", -i); printBinaryInt("j", j); printBinaryInt("i & j", i & j); printBinaryInt("i | j", i | j); printBinaryInt("i ^ j", i ^ j); printBinaryInt("i 5", i 5); printBinaryInt("i >> 5", i >> 5); printBinaryInt("(~i) >> 5", (~i) >> 5); printBinaryInt("i >>> 5", i >>> 5); printBinaryInt("(~i) >>> 5", (~i) >>> 5); long l = rand.nextLong(); long m = rand.nextLong(); printBinaryLong("-1L", -1L); printBinaryLong("+1L", +1L); long ll = 9223372036854775807L; printBinaryLong("maxpos", ll); long lln = -9223372036854775808L; printBinaryLong("maxneg", lln); printBinaryLong("l", l); printBinaryLong("~l", ~l); printBinaryLong("-l", -l); printBinaryLong("m", m); printBinaryLong("l & m", l & m); printBinaryLong("l | m", l | m); printBinaryLong("l ^ m", l ^ m); printBinaryLong("l 5", l 5); printBinaryLong("l >> 5", l >> 5); printBinaryLong("(~l) >> 5", (~l) >> 5); printBinaryLong("l >>> 5", l >>> 5); printBinaryLong("(~l) >>> 5", (~l) >>> 5); static void printBinaryInt(String s, int i) { print(s + ", int: " + i + ", binary:\n " + Integer.toBinaryString(i)); static void printBinaryLong(String s, long l) { print(s + ", long: " + l + ", binary:\n " + Long.toBinaryString(l)); /* Output: -1, int: -1, binary: 11111111111111111111111111111111 +1, int: 1, binary: 1 maxpos, int: 2147483647, binary: 1111111111111111111111111111111 maxneg, int: -2147483648, binary: 10000000000000000000000000000000 i, int: -1172028779, binary: 10111010001001000100001010010101 ~i, int: 1172028778, binary: 1000101110110111011110101101010 -i, int: 1172028779, binary: 1000101110110111011110101101011 j, int: 1717241110, binary: 1100110010110110000010100010110 i & j, int: 570425364, binary: 100010000000000000000000010100 i | j, int: -25213033, binary: 11111110011111110100011110010111 i ^ j, int: -595638397, binary: 11011100011111110100011110000011 i 5, int: 1149784736, binary: 1000100100010000101001010100000 i >> 5, int: -36625900, binary: 11111101110100010010001000010100 (~i) >> 5, int: 36625899, binary: 10001011101101110111101011 i >>> 5, int: 97591828, binary: 101110100010010001000010100 (~i) >>> 5, int: 36625899, binary: 10001011101101110111101011. .. *///:~ Los dos métodos del final, printBinaryInt() y printBinaryLong(), cogen un valor int o long respectivamente y lo imprimen en formato binario junto con una cadena de caracteres descriptiva. Además de presentar el fruto de aplicar todos los operadores bit a bit para valores int y long, el ejemplo también presenta los valores mínimo, máximo, +1 y -1 para int y long para que vea el apariencia que tienen. El bit más alto representa el signo: 0 implica efectivo y 1 negativo. En el ejemplo se presenta la salida de la fracción correspondiente a los valores int. La representación binaria de los número se designa complemento a dos con signo. Ejercicio 11. Comienza con un número que tenga un uno binario en la posición más significativa (consejo: utilice una constante hexadecimal). Utiliza el operador de desplazamiento a la derecha con signo, desplaza el valor a través de todas sus posiciones binarias, mostrando cada vez el fruto con Integer.toBinaryString(). Ejercicio 12. Comienza con un número cuyos dígitos binarios sean todos iguales a uno. A continuación desplázalo a la izquierda y emplea el operador de desplazamiento a la derecha sin signo para desplazarlo a través de todas sus posiciones binarias, visualizando los frutos con Integer.toBinaryString(). Ejercicio 13. Escribe un método que muestre valores char en formato binario. Ejecútelo utilizando varios caracteres diferentes. Operador ternario if - else El operador if - else tiene tres operandos. La expresión es de la forma: expresión - booleana ? valor0 : valor1 Si expresión - booleana es true, se evalúa valor0, en caso de que sea false, se evalúa valor1. Se podría utilizar una instrucción if - else normal, pero el operador if - else ternario es más compacto. Sin embargo hay que tener cuidado a la hora de usarlo ya que el código resultante puede ser escaso legible. Vamos a ver un ejemplo en el que se emplea el operador ternario e if - else normal: //: operators/TernaryIfElse.java import static net.mindview.util.Print.*; public class TernaryIfElse { static int ternary(int i) { return i 10 ? i * 100 : i * 10; static int standardIfElse(int i) { if(i 10) return i * 100; else return i * 10; public static void main(String[] args) { print(ternary(9)); print(ternary(10)); print(standardIfElse(9)); print(standardIfElse(10)); /* Output: 900 100 900 100 *///:~ El código de ternary() es más compacto entretanto que el código de standardIfElse() es más sencillo de entender y hay que escribir más caracteres. Hay que asegurarse bien de cuándo utilizar el operador ternario, puede convenir cuando se quiera configurar una variable con uno de dos valores posibles. Operadores + y += para String Los operadores + y += pueden usarse para concatenar cadenas. Esta sobrecarga de operadores se añadió en C++, para que los programadores pudieran agregar nuevos significados a casi cualquier operador. Sin embargo, en Java esta característica no existe, por tanto, no se pueden agregar más funcionalidades de las que tienen a los distintos operadores, a diferencia de C++ y C#. En Java si una expresión inicia con String, todos los operandos que siguen también tendrán que ser cadenas de caracteres, (el compilador transforma automáticamente a String toda secuencia de caracteres encerrada entre comillas dobles). Veamos un ejemplo: //: operators/StringOperators.java import static net.mindview.util.Print.*; public class StringOperators { public static void main(String[] args) { int x = 0, y = 1, z = 2; String s = "x, y, z "; print(s + x + y + z); print(x + + s); // Converts x to a String s += "(summed) = "; // Concatenation operator print(s + (x + y + z)); print("" + x); // Shorthand for Integer.toString() /* Output: x, y, z 012 0 x, y, z x, y, z (summed) = 3 0 *///:~ El fruto de la expresión print(s + x + y + z) es x, y, z 012, en espacio de x, y, z 3. Esto es porque el compilador convierte las variables x, y y z a String y concatena las cadenas de caracteres en espacio de calcular primero la suma. La segunda expresión de impresión print(x + + s) convierte la variable inicial x a String, por lo que la conversión a cadena no depende de qué es lo que haya primero. El operador += agrega una cadena de caracteres a s, y s se transforma en x, y, z (summed) =. La expresión print(s + (x + y + z)) encierra entre paréntesis a los valores enteros por lo que se realiza la suma antes de convertir el fruto a String. La última expresión print("" + x) realiza una conversión de entero a String de x sin necesidad de invocar al método Integer.toString(). Yerros comunes a la hora de utilizar operadores Uno de los yerros más comunes es no incluir paréntesis cuando no se está seguro de cómo se evaluará una expresión. En la próximo expresión: while (x=y){ //.... En espacio de emplear el operador de equivalencia (==) se emplea el de asignación (=). El compilador aguarda un valor boolean, pero el fruto de esta expresión no es de tipo boolean y no realizará ninguna conversión a dividir de un valor int, por lo que dará un yerro en tiempo de compilación. Este yerro no es detectado por el compilador si x e y son de tipo boolean, en cuyo caso (x=y) sería legal, aunque su uso probablemente es un yerro. En C y C++ los operadores bit a bit AND y OR emplean los caracteres & y |, entretanto que los operadores lógicos emplean && y || respectivamente, por tanto es muy sencillo equivocarse. En Java no se faculta contratar un algun tipo de datos en un espacio donde no sea adecuado hacerlo. Operadores de proyección La palabra proyección (cast) hace referencia a la conversión explícita de datos de un tipo a otro. Java cambiará un tipo de datos a otro cada vez que sea necesario. Si se asigna a una variable de tipo float un valor entero, el compilador convertirá automáticamente el valor int a float. El mecanismo de conversión nos faculta hacer esta conversión de forma explícita, o forzarla en situaciones donde no tenga lugar. Para hacer una proyección se pone a la izquierda del valor que haya que convertir, entre paréntesis, el tipo de datos deseado. Lo vemos con un ejemplo: //: operators/Casting.java public class Casting { public static void main(String[] args) { int i = 200; long lng = (long)i; lng = i; // "Widening," so cast not really required long lng2 = (long)200; lng2 = 200; // A "narrowing conversion": i = (int)lng2; // Cast required ///:~ Se puede aplicar una proyección tanto a los valores numéricos como a las variables. En el ejemplo vemos determinadas proyecciones superfluas (long lng = (long)i; y long lng2 = (long)200;), ya que el compilador promocionará automáticamente un valor int a long cuando sea necesario. Sin embargo, estas proyecciones superfluas pueden destacar la operación o clarificar el código. En otras situaciones (i = (int)lng2;) es necesaria la proyección para que el código se compile correctamente. Cuando realizamos una conversión de estrechamiento (pasamos de un tipo de datos que puede albergar más información a otro que no faculta tanta), corremos el riesgo de perder información. En estos casos el compilador nos obliga a hacer una proyección. En cuanto a la conversión de ensanchamiento (pasamos de un tipo de datos que puede albergar menos información a otro que puede albergar más), no hace falta una proyección explícita ya que el nuevo tipo albergará con creces la información del tipo anterior. Java faculta proyectar cualquier tipo primitivo a cualquier otro, excepto en el caso de boolean, que no faculta ningún tipo de proyección. Los tipos de clase tampoco facultan proyecciones: para convertir uno de estos tipos en otro deben existir métodos especiales. Truncamiento y redondeo Cuando se realizan conversiones de estrechamiento hay que prestar vigilancia al truncamiento y redondeo. Por ejemplo, si poseemos el valor en coma flotante 29,7 y lo proyectamos sobre un int, ¿el valor resultante será 30 o 29? Vamos a verlo en un ejemplo: //: operators/CastingNumbers.java // What happens when you cast a float // or double to an integral value? import static net.mindview.util.Print.*; public class CastingNumbers { public static void main(String[] args) { double above = 0.7, below = 0.4; float fabove = 0.7f, fbelow = 0.4f; print("(int)above: " + (int)above); print("(int)below: " + (int)below); print("(int)fabove: " + (int)fabove); print("(int)fbelow: " + (int)fbelow); /* Output: (int)above: 0 (int)below: 0 (int)fabove: 0 (int)fbelow: 0 *///:~ Como vemos, cuando proyectamos un float o double a un valor entero, se trunca el número correspondiente. Si deseamos que el fruto se redondee poseemos que utilizar los métodos round() de java.lang.Math. //: operators/RoundingNumbers.java // Rounding floats and doubles. import static net.mindview.util.Print.*; public class RoundingNumbers { public static void main(String[] args) { double above = 0.7, below = 0.4; float fabove = 0.7f, fbelow = 0.4f; print("Math.round(above): " + Math.round(above)); print("Math.round(below): " + Math.round(below)); print("Math.round(fabove): " + Math.round(fabove)); print("Math.round(fbelow): " + Math.round(fbelow)); /* Output: Math.round(above): 1 Math.round(below): 0 Math.round(fabove): 1 Math.round(fbelow): 0 *///:~ Promoción En Java si se hacen operaciones matemáticas o bit a bit sobre tipos de datos más chicos que int (char, byte o short), dichos valores serán promocionados a int antes de hacer las operaciones y el fruto será un int. Por tanto, si se desea asignar el fruto del nuevo tipo al más chico es indispensable contratar una proyección, perdiendo de esta forma información. Generalmente, dentro de una expresión el tipo de datos de gran dimensión es el que decide el dimensión del fruto de esa expresión, si multiplicamos un float por un double obtendremos un double, si sumamos un int y un long obtendremos un long, etc. Java no tiene operador "sizeof" En C y C++ el operador sizeof() nos dice el número de bytes asignado a un fundamento de datos. La razón del uso de sizeof() es la portabilidad, ya que los distintos tipos de datos pueden tener distintos dimensiónes en diferentes máquinas, así, el programador debe averiguar el dimensión de esos tipos a la hora de hacer operaciones que sean sensibles al dimensión. Una computadora puede Guardar los enteros en 32 bits, entretanto que otra podría Guardarlos en 16 bits. La computadora de 32 bits podría así Guardar más valores que la de 16 bits. Java no requiere un operador sizeof ya que los tipos de datos tienen el mismo dimensión en todas las computadoras. Compendio de operadores A continuación poseemos un ejemplo que presenta qué tipos de datos primitivos pueden utilizarse con determinados operadores concretos. Es el mismo ejemplo repetido una y otra vez pero empleando distintos tipos de datos primitivos. Las líneas con yerros están desactivadas con comentarios de tipo //!. //: operators/AllOps.java // Tests all the operators on all the primitive data types // to show which ones are accepted by the Java compiler. public class AllOps { // To accept the results of a boolean test: void f(boolean b) { void boolTest(boolean x, boolean y) { // Arithmetic operators: //! x = x * y; //! x = x / y; //! x = x % y; //! x = x + y; //! x = x - y; //! x++; //! x--; //! x = +y; //! x = -y; // Relational and logical: //! f(x > y); //! f(x >= y); //! f(x y); //! f(x = y); f(x == y); f(x != y); f(!y); x = x && y; x = x || y; // Bitwise operators: //! x = ~y; x = x & y; x = x | y; x = x ^ y; //! x = x 1; //! x = x >> 1; //! x = x >>> 1; // Compound assignment: //! x += y; //! x -= y; //! x *= y; //! x /= y; //! x %= y; //! x = 1; //! x >>= 1; //! x >>>= 1; x &= y; x ^= y; x |= y; // Casting: //! char c = (char)x; //! byte b = (byte)x; //! short s = (short)x; //! int i = (int)x; //! long l = (long)x; //! float f = (float)x; //! double d = (double)x; void charTest(char x, char y) { // Arithmetic operators: x = (char)(x * y); x = (char)(x / y); x = (char)(x % y); x = (char)(x + y); x = (char)(x - y); x++; x--; x = (char)+y; x = (char)-y; // Relational and logical: f(x > y); f(x >= y); f(x y); f(x = y); f(x == y); f(x != y); //! f(!x); //! f(x && y); //! f(x || y); // Bitwise operators: x= (char)~y; x = (char)(x & y); x = (char)(x | y); x = (char)(x ^ y); x = (char)(x 1); x = (char)(x >> 1); x = (char)(x >>> 1); // Compound assignment: x += y; x -= y; x *= y; x /= y; x %= y; x = 1; x >>= 1; x >>>= 1; x &= y; x ^= y; x |= y; // Casting: //! boolean bl = (boolean)x; byte b = (byte)x; short s = (short)x; int i = (int)x; long l = (long)x; float f = (float)x; double d = (double)x; void byteTest(byte x, byte y) { // Arithmetic operators: x = (byte)(x* y); x = (byte)(x / y); x = (byte)(x % y); x = (byte)(x + y); x = (byte)(x - y); x++; x--; x = (byte)+ y; x = (byte)- y; // Relational and logical: f(x > y); f(x >= y); f(x y); f(x = y); f(x == y); f(x != y); //! f(!x); //! f(x && y); //! f(x || y); // Bitwise operators: x = (byte)~y; x = (byte)(x & y); x = (byte)(x | y); x = (byte)(x ^ y); x = (byte)(x 1); x = (byte)(x >> 1); x = (byte)(x >>> 1); // Compound assignment: x += y; x -= y; x *= y; x /= y; x %= y; x = 1; x >>= 1; x >>>= 1; x &= y; x ^= y; x |= y; // Casting: //! boolean bl = (boolean)x; char c = (char)x; short s = (short)x; int i = (int)x; long l = (long)x; float f = (float)x; double d = (double)x; void shortTest(short x, short y) { // Arithmetic operators: x = (short)(x * y); x = (short)(x / y); x = (short)(x % y); x = (short)(x + y); x = (short)(x - y); x++; x--; x = (short)+y; x = (short)-y; // Relational and logical: f(x > y); f(x >= y); f(x y); f(x = y); f(x == y); f(x != y); //! f(!x); //! f(x && y); //! f(x || y); // Bitwise operators: x = (short)~y; x = (short)(x & y); x = (short)(x | y); x = (short)(x ^ y); x = (short)(x 1); x = (short)(x >> 1); x = (short)(x >>> 1); // Compound assignment: x += y; x -= y; x *= y; x /= y; x %= y; x = 1; x >>= 1; x >>>= 1; x &= y; x ^= y; x |= y; // Casting: //! boolean bl = (boolean)x; char c = (char)x; byte b = (byte)x; int i = (int)x; long l = (long)x; float f = (float)x; double d = (double)x; void intTest(int x, int y) { // Arithmetic operators: x = x * y; x = x / y; x = x % y; x = x + y; x = x - y; x++; x--; x = +y; x = -y; // Relational and logical: f(x > y); f(x >= y); f(x y); f(x = y); f(x == y); f(x != y); //! f(!x); //! f(x && y); //! f(x || y); // Bitwise operators: x = ~y; x = x & y; x = x | y; x = x ^ y; x = x 1; x = x >> 1; x = x >>> 1; // Compound assignment: x += y; x -= y; x *= y; x /= y; x %= y; x = 1; x >>= 1; x >>>= 1; x &= y; x ^= y; x |= y; // Casting: //! boolean bl = (boolean)x; char c = (char)x; byte b = (byte)x; short s = (short)x; long l = (long)x; float f = (float)x; double d = (double)x; void longTest(long x, long y) { // Arithmetic operators: x = x * y; x = x / y; x = x % y; x = x + y; x = x - y; x++; x--; x = +y; x = -y; // Relational and logical: f(x > y); f(x >= y); f(x y); f(x = y); f(x == y); f(x != y); //! f(!x); //! f(x && y); //! f(x || y); // Bitwise operators: x = ~y; x = x & y; x = x | y; x = x ^ y; x = x 1; x = x >> 1; x = x >>> 1; // Compound assignment: x += y; x -= y; x *= y; x /= y; x %= y; x = 1; x >>= 1; x >>>= 1; x &= y; x ^= y; x |= y; // Casting: //! boolean bl = (boolean)x; char c = (char)x; byte b = (byte)x; short s = (short)x; int i = (int)x; float f = (float)x; double d = (double)x; void floatTest(float x, float y) { // Arithmetic operators: x = x * y; x = x / y; x = x % y; x = x + y; x = x - y; x++; x--; x = +y; x = -y; // Relational and logical: f(x > y); f(x >= y); f(x y); f(x = y); f(x == y); f(x != y); //! f(!x); //! f(x && y); //! f(x || y); // Bitwise operators: //! x = ~y; //! x = x & y; //! x = x | y; //! x = x ^ y; //! x = x 1; //! x = x >> 1; //! x = x >>> 1; // Compound assignment: x += y; x -= y; x *= y; x /= y; x %= y; //! x = 1; //! x >>= 1; //! x >>>= 1; //! x &= y; //! x ^= y; //! x |= y; // Casting: //! boolean bl = (boolean)x; char c = (char)x; byte b = (byte)x; short s = (short)x; int i = (int)x; long l = (long)x; double d = (double)x; void doubleTest(double x, double y) { // Arithmetic operators: x = x * y; x = x / y; x = x % y; x = x + y; x = x - y; x++; x--; x = +y; x = -y; // Relational and logical: f(x > y); f(x >= y); f(x y); f(x = y); f(x == y); f(x != y); //! f(!x); //! f(x && y); //! f(x || y); // Bitwise operators: //! x = ~y; //! x = x & y; //! x = x | y; //! x = x ^ y; //! x = x 1; //! x = x >> 1; //! x = x >>> 1; // Compound assignment: x += y; x -= y; x *= y; x /= y; x %= y; //! x = 1; //! x >>= 1; //! x >>>= 1; //! x &= y; //! x ^= y; //! x |= y; // Casting: //! boolean bl = (boolean)x; char c = (char)x; byte b = (byte)x; short s = (short)x; int i = (int)x; long l = (long)x; float f = (float)x; ///:~ Si nos fijamos boolean es bastante limitado. Una variable de este tipo puede ser true y false, y se puede verificar si el valor es verdadero o falso, pero no se pueden sumar valores booleanos ni hacer ninguna otra operación. En char, byte y short se puede ver el fruto de la promoción con los operadores aritméticos. Toda operación aritmética entre cualquiera de estos tipos genera un fruto int que debe ser proyectado al tipo original para hacer la asignación a dicho tipo. Con los valores int no es necesaria ninguna proyección ya que todo es de tipo int. No todas las operaciones son seguras ya que si se multiplican dos int que sean suficientemente grandes, puede producirse un desbordamiento en el fruto. Lo vemos en el próximo ejemplo: //: operators/Overflow.java // Surprise! Java lets you overflow. public class Overflow { public static void main(String[] args) { int big = Integer.MAX_VALUE; System.out.println("big = " + big); int bigger = big * 4; System.out.println("bigger = " + bigger); /* Output: big = 2147483647 bigger = -4 *///:~ No se obtiene ningún yerro o advertencia del compilador, ni tampoco un yerro en tiempo de ejecución. Las asignaciones compuestas (x+=y) no necesitan proyecciones para char, byte o short, inclusive cuando esté realizando promociones que provocan los mismos frutos que las operaciones aritméticas directas. Esto es algo admirable pero la probabilidad de no incluir la proyección simplifica el código. Con la excepción de boolean, podemos proyectar cualquier tipo primitivo sobre cualquier otro tipo primitivo. Hay que tener en cuenta las conversiones de estrechamiento a la hora de hacer proyecciones sobre tipos de menor tamaño. Ejercicio 14. Escribe un método que tome dos argumentos de tipo String y utilice todas las comparaciones boolean para comparar las dos cadenas de caracteres e imprimir los resultados. Para las comparaciones == y !=, realiza también la prueba con equals(). En main(), invoca el método que haya escrito, utilizando varios objetos String distintos

Entradas populares