jueves, 13 de julio de 2017

Mi estrategia para generar Ahorro

Hoy se cumple un año desde que me dispuse iniciar un agresivo plan de ahorros, no hace falta mencionar la importancia de contar con un ahorro o de disminuir gastos para cubrir una deuda, en mi caso para primeramente reducir una deuda. Aquí les comparto algunas acciones que he tomado, no necesariamente están ordenados.

1.- Usar la bicicleta para ir de la casa al trabajo
Si si, ya se que viajar en bicicleta es peligroso, pero según mi experiencia esto es más que un mito, al menos en Santiago de Chile hay una gran libertad para moverse en bicicleta.

Costo de viajar en metro

ConceptoMonto
Diario x 21 480
Semanal x 57 400
Mensual x 429 600
Anual x 12355 200
TOTAL355 200

Costo de Viajar en Bicicleta


ConceptoMonto
Bicicleta MTB210 000
Candado18 000
Refaccion Frenos11 500
Refaccion Frenos6 900
TOTAL246 400
Si consideramos el costo de la bicicleta dentro del gasto, tenemos:
Ahorro = 355 200 - 246 400 = 108 800

Si sólo consideramos el gasto en refacciones para el mantenimiento, tenemos:
Ahorro = 355 200 - 18 400 = 336 800

Como pueden observar, incluso considerando el costo de la bicicleta + candado, se obtiene un ahorro considerable.

2.- Elegir sabiamente la tarjeta de credito
En el mundo globalizado en el que vivimos contar con una tarjeta de credito se vuelve una necesidad, las tarjetas de credito tienen costos asociados, después de mucho investigar me quedo con dos tarjetas de credito, ademas les explicaré un truco qué encontré.

Tarjeta Lider Mastercard Preferente


InstituciónLider - WalmartObservaciones
Costo de mantencion0
Comision compra internacional0
Seguros Integrales0
Seguro desgravamen700No es obligatorio pero es recomendable
Beneficios- Se puede pagar en caja y
con otra tarjeta de credito
como medio de pago

Tarjeta Santander 3 2 1

InstituciónSantander
Costo de mantencion0Hay que tener buen historial y llorarle al
banco para lograr este beneficio
Comision compra internacional3,50%No usarla para compras internaciones
Seguros Integrales0
Seguro desgravamen0
BeneficiosDevuelve el 3% en las compras en Combustible (hasta $3.000 todos los meses)
Devuelve el 2% en las compras en Grandes Tiendas (hasta $8.000 todos los meses)
Devuelve el 1% en las compras en Supermercados (hasta $4.000 todos los meses)
En total, devuelve hasta $15.000 todos los meses y hasta $180.000 al año

El truco que yo aplico es usar la tarjeta lider para todas mis compras y pago el monto facturado en caja con la tarjeta de santander, al pagar en caja se considera un gasto del rubro Supermercados y me devuelven el 1% 


martes, 20 de junio de 2017

Conquistando la cima del Manquehuito

Hace meses que me nació el deseo de tomarme una foto con la imponente cordillera detrás de mi, la universidad, el trabajo y la salud, me lo habían estado impidiendo. Me puse a buscar un lugar que fuera fácil de acceder y que permitiera contemplar la cordillera. Recordé que había escuchado del cerro Manquehuito, en voz de un excompañero de ciclismo. Este domingo justo coincidió con un sábado de lluvia, era el día perfecto, tenía que subir.


Llamé a mi amigo Pablo Veneno, un cuate aperrado, que disfruta de los retos, quien prefiere un día de actividad a una noche de fiesta mientras te emborrachas hasta el amanecer. No me defraudó y acepto acompañarme.
Sábado en la noche, fui a una fiesta, esta vez me propuse no tomar nada de alcohol y me mantuve firme, nada de alcohol. Disfruté del ambiente, de la comida y del baile. Me retiré temprano para reponer energía y partir al cerro el domingo en la mañana.
Domingo en la maña me despierto temprano, saco a pasear a mi perrito Tommy, desayuno y preparo la mochila, llevo frutas como plátano y naranja, un litro de agua (debí haber llevado 2 litros), galletas y una colación.
Al llegar al punto de encuentro donde quede de juntarme con Pablo, me llevé una grata sorpresa, se habían unido más personas, incluso uno de ellos ya había hecho el recorrido por lo que su experiencia fue bien recibida.
Por fortuna el transporte publico te deja muy cerca del sendero para subir al cerro, caminamos no más de 2 horas, un camino muy empinado, fuimos despacio, a nuestro ritmo. Mientras caminaba, pensaba en que quizás no lograría llegar a la cima, el viento, el frió y un malestar en la garganta complicaban el camino. Pero a pesar de dar pasos lentos y pequeños, mientras transcurría el tiempo estábamos cada vez más cerca de la cima, así hasta que finalmente llegamos.
Una vez arriba, se siente el aire limpio al respirar, estar ahí valió todo el esfuerzo, aire limpio y una vista espectacular, de hecho mientras escribo estás lineas recuerdo perfectamente cada detalle, el dolor en las piernas, el frió, el viento helado y la garganta con dolor, pero nada de esto importaba, ya estaba en la cima, eso era lo que importaba.
El descenso fue más rápido, pero las piernas flaqueaban, el frió aumentaba, estaba agotado pero feliz, sentir que logré cumplir mi deseo, tomarme una foto con la cordillera de fondo.
Total gastado: 5 USD












domingo, 23 de abril de 2017

Punto de Inflexión en mi vida

Este año viene acompañado de muchas decepciones, estoy decepcionado de mi mismo, de mi persona, de lo que soy y de lo que tengo. Creo que decepcionarse de uno mismo no es malo, lo malo es saberlo y no actuar. He llegado a aceptar que pareciera que durante casi 30 años he estado dormido mientras el mundo avanzaba, y de pronto despierto, mi burbuja se rompe y me enfrento a la realidad, a un mundo salvaje. Te sientes decepcionado cuando descubres que no estás preparado para hacerle frente a las adversidades de la vida, que mientras el mundo evolucionaba tu te dormías. Pero ya desperté y ahora tengo un deseo ferviente de cambiar, de darle un giro inesperado a mi vida y avanzar hacia objetivos definidos.
Voy a iniciar un largo camino para adquirir nuevas habilidades, un camino en el que el esfuerzo, sacrificio y dedicación son fundamentales.

El reto para la primera semana será llegar puntual y bien presentable al trabajo

jueves, 9 de marzo de 2017

Java: Leer una cadena desde consola e imprimirla al reves

Es muy común en las clases de programación de Java el solicitar un programa que lea una cadena desde la consola y luego la imprima al reves. Para ello podemos hacerlo de dos formas, la primera es usar la clase StringBuilder, la segunda es desarrollar un metodo propio. Aquí les dejo un programa en en Java que usa las dos formas.


/*
 * Tutorials
 * Copyright (C) 20017 Roberto Lopez marcos.roberto.lopez@gmail.com
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 * 
 * Roberto Lopez
 * CDMX, México
 * https://marcosrobertos.blogspot.com
 * Email: marcos.roberto.lopez@gmail.com
 */
 
package com.rlopez.tutorials.string;

import java.util.Scanner;

/**
 *
 * @author Cliente
 */
public class ReverseString {
   public static void main(String args[]){
      System.out.println("Ingresa una palabra [presione enter para confirmar]");
      Scanner scanner = new Scanner(System.in);
      String world = scanner.nextLine();
      //first way create a string builder instance, reverse the same instance
      //of string builder
      System.out.println("Reverse using StringBuilder.reverse(): "
      + (new StringBuilder(world).reverse()));
      //second way use my own method, reverse and return a new instance of
      //string
      System.out.println("Reverse using my owner reverse(): "
      + (ReverseString.reverse(world)));
   }
   
   public static String reverse(String toReverse){
      char characters[] = new char[toReverse.length()];
      int j = 0;
      for(int i = toReverse.length() - 1; i >= 0; i--){
         characters[j++] = toReverse.charAt(i);
      }
      return new String(characters);
   }
}

Salida:

compile-single:
run-single:
Ingresa una palabra [presione enter para confirmar]
Hola buenos días
Reverse using StringBuilder.reverse(): saíd soneub aloH
Reverse using my owner reverse(): saíd soneub aloH

viernes, 24 de febrero de 2017

Instalar Oracle Java JDK8 en Ubuntu 16.04

Introducción

Me ausente de Linux por un periodo de 5 años, hoy regreso y lo encuentro mucho más guapo, he decidido volver. Como fanático de la programación lo primero que haré será instalar Java + Netbeans. Ubuntu por defecto viene con OpenJDK, en el pasado tuve malas experiencias con OpenJDK, prefiero instalar el JDK de Oracle.

Paso 1. Verificar que JDK tenemos

La instalación de Ubuntu que tengo no viene instalado con el OpenJDK, para ver si tenemos alguna versión instalada ejecutamos lo siguiente:














En caso de tener instalado el OpenJDK, hay que desinstalarlo, para hacerlo seguir este tutorial


Paso 2. Agregamos el repositorio de Java a nuestra lista de fuentes


Agregamos el repositorio a nuestra lista de fuentes, ejecutar el siguiente comando:















Nos pide confirmación para continuar, presionar enter para continuar














Si todo va bien veremos esta última pantalla













Paso 3. Actualizamos nuestra lista de fuentes

Para actualizar nuestra lista de fuentes ejecutamos lo siguiente:










Al terminar veremos la siguiente pantalla

















Paso 4. Instalar Java JDK 8

Ejecutamos el siguiente comando







Nos pedirá confirmación, presionar Y y luego enter













Nos advierte que debemos aceptar la Licencia















Aceptamos la Licencia













Esperamos unos minutos y al terminar muestra la siguiente pantalla














Tomar nota del mensaje con el titulo "important", para no tener ningún conflicto vamos a instalar lo que nos pide







Al finalizar veremos la siguiente pantalla













Reiniciamos el equipo y comprobamos la instalación, ejecutamos los siguientes dos comando














Así hemos finalizado con éxito la instalación de Oracle Java JDK 8 en Ubuntu 16.04

viernes, 17 de febrero de 2017

Maven: Que es?

Introducción

Hace ya un par de meses que decidí estudiar la plataforma JEE, la mayoría de los tutoriales que hay en la web están basados en Maven, la mayoría de esos ejemplos no funcionan a la primera ya que los archivos de configuración de Maven pueden estar obsoletos, diferencias entre el ambiente,distinto IDE, diferentes versiones de los componentes, y así. Hay que tener conocimientos sólidos en Maven para adaptar los tutoriales a nuestro ambiente particular.

Es así que decidí estudiar Maven a profundidad, hay un buen número de tutoriales y referencias en la web en español, pero no encontré uno escrito a profundidad, que explique con lujo de detalle todos los conceptos. He obtenido un libro muy completo de Maven, está en ingles, trataré de traducirlo para tenerlo como guía y aprender todos los conceptos de Maven.

¿Qué es Maven?

La respuesta a esta pregunta depende de quien lo pregunte, la mayoría de los usuarios que usan Maven lo consideran cómo una "herramienta build": herramienta usada para compilar, empaquetar y distribuir módulos desde el código fuente. Ingenieros y gerentes de proyectos podrían referirse a Maven cómo algo más completo: una herramienta de gestión(administración) de proyectos. ¿Cual es la diferencia? Una herramienta build como Ant, está enfocado exclusivamente en pre procesar, compilar, empaquetar, probar y distribuir. Una herramienta de gestión de proyectos cómo Maven proporciona un amplio conjunto de características encontrados en una herramienta build, es decir, es una herramienta build y algo más. Además de ser una herramienta build, Maven también puede generar distintos tipos de reportes, generar sitios web, y facilitar la comunicación entre miembros de un equipo de desarrollo.
Una definición más formal de Apache Maven: Maven es una herramienta de gestión de proyectos, que incluye un pom (Project Object Model) el modelo de objetos del proyecto, un conjunto de estándares, un ciclo de vida del proyecto, un sistema de gestión de dependencias, y lógica para ejecutar plugins en las fases del ciclo de vida. Cuando tu usas Maven, tu describes tu proyecto usando un pom definido correctamente, después Maven aplicará lógica de forma transversal (profundidad máxima para cada objeto) al conjunto de plugins compartidos o personalizados. Más adelante veremos que son los plugins.
No dejes que te intimide el hecho de que Maven sea una herramienta de gestión de proyectos. Si sólo estabas buscando una herramienta build, Maven puede hacer el trabajo. De hecho. los primeros artículos de este libro cubrirán la mayoría de los casos de usos comunes: usando Maven para construir y distribuir tu proyecto.

Convención Sobre Configuración

Convención sobre Configuración, también conocido como CoC es un concepto simple que busca minimizar el número de decisiones que un desarrollador necesita hacer, ganando así en simplicidad pero no perdiendo flexibilidad por ello.
Frameworks populares como Ruby on Rails y EJB3 han comenzado a adquirir estos principios como respuesta a la complejidad de los frameworks, tal como es el caso de la especificación inicial EJB 2.1. Para ilustrar el concepto de Convención sobre Configuración, considere la persistencia en EJB3: todo lo que necesitas hacer para tener un bean persistente es agregar a tu clase la anotación @Entity. El framework asume que el nombre de la tabla y columnas están en base al nombre de la clase y sus atributos. Sin embargo tu puedes sobreescribir estos nombres en caso de ser necesario, pero en la mayoría de los casos encontrarás que usar el framework con sus configuraciones por defecto te permitirá una rápida ejecución del proyecto.
Maven incorpora este concepto proporcionando configuraciones y comportamientos por defecto para los projectos. Sin ninguna configuración, se asume que el código fuente estará en ${basedir}/src/main/java y se asume que los recursos estarán en ${basedir}/src/test, y se asume que un proyecto generará un archivo JAR. Maven asume que tu quieres el código byte compilado en ${basedir}/target/classes y entonces crear en ${basedir}/target un archivo JAR para distribuir. Mientras esto puede parecer trivial, considera el hecho de que en Ant se tiene que definir la ubicación de todos estos directorios. Ant no tiene idea de donde pueden estar el código fuente o los recursos en un proyecto. Tu tienes que proporcionar explicita mente esta información. La adopción del concepto Convención sobre configuración de Maven, va más allá de simple ubicaciones de directorios. Los plugins principales de Maven aplican un conjunto común de convenciones para compilar código fuente, empaquetar distribuciones, generar sitios web, y muchos otros procesos. Si tu sigues las convenciones, Maven requerirá esfuerzos mínimos, sólo coloca el código fuente en el directorio correcto y Maven se encargará del resto.
Un efecto secundario de usar sistemas que siguen el concepto de "Convención sobre Configuración" es que el usuario final puede sentir que está siendo forzado a usar un enfoque o metodología particular. Si bien es cierto que Maven tiene algunas opiniones bases que no deberían ser desafiadas, la mayoría de las características que vienen por defecto pueden ser personalizados. Por ejemplo, la ubicación  del código fuente de un proyecto y la ubicación de los recursos, estos pueden ser personalizados, los nombres de los archivos JAR también pueden ser personalizados, . Si no quieres seguir la convención, Maven te permitirá adaptar las características por defecto con tal de adaptarlos a tus requerimientos específicos.


Referencia:
Maven: The complete Reference, Sonatype, http://www.sonatype.org/nexus/resources/resources-book-links-and-downloads/

viernes, 10 de febrero de 2017

Java: Localizar y leer recursos (imágenes, properties o audio) independiente de la ubicación

Introducción

Localizar y leer recursos puede ser una tarea confusa y frustrante cuando no se tienen fundamentos sólidos, incluso a mi se me olvidan de vez en cuando, es por ello que decidí escribir esta entrada, para consultarla cuando la necesite.
Un recurso puede ser un archivo de texto o binario, imagen, audio, etc,. Usualmente los programas o clases necesitan leer estos recursos de forma independiente a la ubicación. De mi experiencia reconozco que la ubicación de un recurso puede coincidir con algunos de estos escenarios:
  • En la misma ubicación donde se encuentra la clase que necesita leer el recurso.
  • En otro paquete dentro del mismo jar donde se encuentra la clase que necesita leer el recurso
  • En un paquete dentro de un jar distinto al jar donde se encuentra la clase que necesita leer el recurso.
  • En un directorio, donde el directorio se encuentra en el classpath.
  • En algún lugar arbitrario dentro de una aplicación web fuera del jar donde se encuentra la clase que necesita leer el recurso

Las clases Class y ClassLoader contienen métodos para localizar y cargar recursos, cuando digo localizar me refiero a que pueden entregarnos una URL del recurso, y por cargar me refiero a que pueden entregarnos una instancia de un InputStream con el cual podemos leer el contenido.

Nota: El Classpath es una lista de directorios asociada a nuestra aplicación, cada aplicación que se ejecuta en la JVM tiene asociada un Classpath.

Nota: El ClassLoader en palabras simples, es una clase responsable de cargar en memoria nuestra clase principal y todas aquellas clases que necesite.

Recursos, nombres y contexto

Un recurso es identificado por una cadena de caracteres la cual se compone de subcadenas de caracteres separados por slashes (/), seguido por el nombre del recurso, es decir, el nombre del recurso es el nombre del recurso más la ruta (path) absoluta o relativa. Cada subcadena debe ser un identificador Java válido.  El nombre del recurso puede ser de la forma shortName o shortName.extension. Ambos shortName y extensión deben ser identificadores Java.
Aquí una referencia completa  de identificadores válidos en Java:
https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html
El nombre del recurso es independiente de la implementación de Java, en particular el separador path, el cual siempre será un slash (/). Sin embargo, la implementación de Java controla los detalles de como los recursos son mapeados en un archivo, base de datos u otro objeto capaz de contener al recurso.
Nota: La interpretación del nombre del recurso es relativo a la instancia del class loader. Los métodos implementados por la clase ClassLoader hacen esta interpretación.

Como localiza Java los recursos

Java buscará el recurso dentro del "ambiente" de la aplicación, consideramos "ambiente" a todos los jars y directorios que se encuentren en el Classpath. La búsqueda y carga de recursos en Java es llamado independiente de la localización porque no es relevante donde el código está corriendo, basta tener el ambiente correcto para encontrar los recursos.
Las clases ClassLoader y Class nos proveen métodos para buscar recursos deseados, es necesario comprender bien el contexto de uso de cada uno de ellos para evitarnos problemas en un futuro y para decidir cual método usar.

Usando métodos de la clase java.lang.Class, búsqueda relativa y absoluta


La clase Class nos proporciona los siguientes dos metodos para la carga de recursos.

public URL getResource(String name)
public InputStream getResourceAsStream(String name)

El metodo getResource() retorna una instancia URL para el recurso. Si el recurso no existe o no está visible debido a consideraciones de seguridad, el metodo retorna null.

Si el código cliente necesita leer el contenido del recurso como una instancia InputStream, se puede hacer una llamada al metodo openStream() de la instancia URL.  Mejor aun, puedes hacer uso del metodo getResourceAsStream() de la clase Class, ambas formas son equivalentes, la unica diferencia es que el método getResourceAsStream() atrapa la excepción IOException y retorna una instancia null de InputStream.
Incluso podemos ir más lejos, si sabemos que el recurso a leer es una imagen podemos obtener el contenido llamando al metodo getContent() de la clase URL, este metodo nos devuelve una instancia de la clase awt.image.ImageProducer y apartir de aquí podemos pintar la imagen en un Component

Los metodos getResource y getResourceAsStream encuentran un recurso a partir del nombre proporcionado, esta busqueda puede ser relativa al paquete del objeto Class o absoluta. Si el recurso con el nombre especificado no se encuentra retornan una instancia null. Hay un conjunto de reglas que se aplican a la busqueda de recursos, estas reglas son implementadas por el ClassLoader de la instancia Class.
Los metodos  getResource y getResourceAsStream de la clase Class delegan la tarea a los métodos de la clase ClassLoader, no sin antes resolver el nombre del recurso de acuerdo a ciertas reglas.

Resolver el nombre del recurso consiste en lo siguiente: si el nombre del recurso no es absoluto, se obtiene el nombre del paquete de la clase asociada al objeto Class, se reemplazan todos los caracteres "." por "/"  y se le antepone al nombre del recurso. En otro caso, si el recurso es absoluto solo se elimina el caracter inicial "/". El nombre de un recurso se considera absoluto si empieza con "/".

Nota: Absoluto respecto a nuestro ambiente, el cual es definido por el ClassLoader y no absoluto con respecto al sistema de archivos del sistema operativo.

Nota: Recordar que después de resolver el nombre del recurso, los métodos de la clase Class delegan la tarea a los métodos de la clase ClassLoader

Usando métodos de la clase ClassLoader

La clase ClassLoader tiene dos metodos para localizar y leer recursos

public URL getResource(String name)
public InputStream getResourceAsStream(String name)

Repito, estos dos métodos son usados por los métodos de la clase Class. En un ambiente Java nos vamos a encontrar con más de un ClassLoader, pudiendo haber una relación entre ellos, cada ClassLoader tiene asociado un directorio al que tiene acceso para cargar las clases, siendo el System Class Loader el que tiene acceso a una lista de directorios, sí, me refiero al Classpath. Es importante conocer cuantos ClassLoader pueden haber en un ambiente Java y como estos están relacionados.

Hay una articulo en la web que explica detalladamente el tema de los ClassLoader, coincido con el autor, así que antes de continuar ver el concepto de ClassLoader 

En resumen, cuando ejecutamos una clase en  la JVM, al menos tres ClassLoader son usados.
  1. Bootstrap class loader.
  2. Extensións class loader.
  3. System class loader

El bootstrap class loader carga las librerías (jars) del núcleo de Java localizado en el directorio <JAVA_HOME>/lib. Esta clase es parte del núcleo de la JVM, esta escrito en código nativo.

El extensions class loader carga las librerías (jars) y directorios que se encuentren en el directorio de extensiones (<JAVA_HOME>/lib/ext, u otro directorio especificado por la propiedad java.ext.dirs ) Esta implementado por la clase sun.misc.Launcher$ExtClassLoader.

El system class loader carga las librerías (jars) y directorios encontrados en el Classpath. Es implementado por la clase sun.misc.Launcher$AppClassLoader.

Las instancias Class Loader siguen una jeraquía, una instancia de Bootstrap class loader puede ser padre de una instancia de Extension class loader, y esta puede ser padre de una instancia de System class loader.
Cuando buscamos un recurso este se busca de arriba hacia abajo, por ejemplo, si a una instancia de System class loader le pedimos un recurso, este se lo pedirá a su padre y su padre se lo pedirá a su padre, así hasta llegar al padre de todos. Si el padre no tiene el recurso se buscará en el hijo, si este no lo tiene se lo pedirá a su hijo, así hasta llegar al System class loader. Todos los Class Loader buscan el recurso de forma absoluta, absoluta a cada uno de los  jar o directorios asociado.

Ahora si, con todos los fundamentos mencionados, es momento de ir a la practica.

Localizar un recurso ubicado en el mismo paquete donde se encuentra la clase que lo necesita

Tengo el siguiente proyecto ya compilado y estructurado como lo muestra la imagen


Vamos a localizar el recurso "duke_wave.png" el cual se encuentra en el mismo paquete que la clase "ResourceLocator". Este recurso está ubicado en dos lugares, dentro de mi proyecto, el cual tiene la ruta absoluta "C:\devel\src\personal\tutorials\tutorials\src\com\rlopez\tutorials\resources" , absoluta en relación al sistema de archivos del Sistema Operativo.
Una vez compilemos el proyecto, explicitamente o ya sea que Netbeans lo haga de forma automática, vamos a tener otro recurso "duke_wave.png", el cual estará ubicado en la ruta absoluta "C:\devel\src\personal\tutorials\tutorials\build\classes\com\rlopez\tutorials\resources", absoluta en relación al sistema de archivos del Sistema Operativo.

Para localizar nuestro recurso lo podemos hacer de dos formas, relativa a nuestra clase o absoluto a nuestro ambiente.

Búsqueda relativa a nuestra clase

public static URL getRelativeResource(String resourceName){
   Class clazz = ResourceLocator.class;
   URL url = clazz.getResource(resourceName);
   return url;
}

Búsqueda absoluta en nuestro ambiente

Al ejecutar la clase main desde Netbeans, se agrega el directorio "C:\devel\src\personal\tutorials\tutorials\build\classes\"al classpath de la aplicación, este directorio pasa a ser parte del ambiente de la aplicación.

public static URL getAbsoluteResource(String resourceName){
   Class clazz = ResourceLocator.class;
   String rpath = "/com/rlopez/tutorials/resources/" + resourceName; 
   URL url = clazz.getResource(rpath);
   return url;
}

Haciendo uso de nuestros métodos

/*
 * Tutorials
 * Copyright (C) 20017 Roberto Lopez marcos.roberto.lopez@gmail.com
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 * 
 * Roberto Lopez
 * CDMX, México
 * Email: marcos.roberto.lopez@gmail.com
 */

package com.rlopez.tutorials.resources;

import java.net.URL;
/**
 *
 * @author Roberto Lopez
 */
public class ResourceLocator {
 
 public static void main(String args[]){
  System.out.println("The App Classpath:" + System.getProperty("java.class.path"));
  System.out.println("Test get resource using relative way");
  URL url = ResourceLocator.getRelativeResource("duke_wave.png");
  System.out.println("Resource [Relative]:" + url.getFile());
  
  System.out.println("Test get resource using Absolute way");
  URL urlAbs = ResourceLocator.getAbsoluteResource("duke_wave.png");
  System.out.println("Resource [Absolute]:" + urlAbs.getFile());
 }
 
 public static URL getRelativeResource(String resourceName){
  Class clazz = ResourceLocator.class;
  URL url = clazz.getResource(resourceName);
  return url;
 }
 
 public static URL getAbsoluteResource(String resourceName){
  Class clazz = ResourceLocator.class;
  String rpath = "/com/rlopez/tutorials/resources/" + resourceName;
  URL url = clazz.getResource(rpath);
  return url;
 }
}

Run:
The App Classpath:C:\devel\src\personal\tutorials\tutorials\build\classes
Test get resource using relative way
Resource [Relative]:/C:/devel/src/personal/tutorials/tutorials/build/classes/com/rlopez/
tutorials/resources/duke_wave.png
Test get resource using Absolute way
Resource [Absolute]:/C:/devel/src/personal/tutorials/tutorials/build/classes/com/rlopez/
tutorials/resources/duke_wave.png


Localizar un recurso en otro paquete dentro del mismo jar donde se encuentra la clase que necesita leer el recurso
Modificamos el proyecto agregando un nuevo paquete

Nuevamente vamos a usar los métodos que definimos anteriormente y vamos a buscar el recurso de forma relativa y absoluta.
En la búsqueda relativa iremos al directorio superior con el comando ".." y hemos realizado una modificación a la búsqueda absoluta.

/*
 * Tutorials
 * Copyright (C) 20017 Roberto Lopez marcos.roberto.lopez@gmail.com
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 * 
 * Roberto Lopez
 * CDMX, México
 * Email: marcos.roberto.lopez@gmail.com
 */

package com.rlopez.tutorials.resources;

import java.net.URL;
/**
 *
 * @author Roberto Lopez
 */
public class ResourceLocator {
 
 public static void main(String args[]){
  System.out.println("The App Classpath:" + System.getProperty("java.class.path"));
  System.out.println("Test get resource using relative way");
  URL url = ResourceLocator.getRelativeResource("../images/duke_wave.png");
  System.out.println("Resource [Relative]:" + url.getFile());
  
  System.out.println("Test get resource using Absolute way");
  URL urlAbs = ResourceLocator.getAbsoluteResource("/com/rlopez/tutorials/images/
duke_wave.png");
  System.out.println("Resource [Absolute]:" + urlAbs.getFile());
 }
 
 public static URL getRelativeResource(String resourceName){
  Class clazz = ResourceLocator.class;
  URL url = clazz.getResource(resourceName);
  return url;
 }
 
 public static URL getAbsoluteResource(String resourceName){
  Class clazz = ResourceLocator.class;
  if(!resourceName.startsWith("/")){
   resourceName = "/" + resourceName;
  }
  URL url = clazz.getResource(resourceName);
  return url;
 }
}

run:
The App Classpath:C:\devel\src\personal\tutorials\tutorials\build\classes
Test get resource using relative way
Resource [Relative]:/C:/devel/src/personal/tutorials/tutorials/build/classes/com/rlopez/
tutorials/images/duke_wave.png
Test get resource using Absolute way
Resource [Absolute]:/C:/devel/src/personal/tutorials/tutorials/build/classes/com/rlopez/
tutorials/images/duke_wave.png

En un paquete dentro de un jar distinto al jar donde se encuentra la clase que necesita leer el recurso



Localizar un recurso en un directorio, donde el directorio se encuentra en el classpath.

Pendiente

Localizar un recurso en algún lugar arbitrario dentro de una aplicación web y fuera del jar donde se encuentra la clase que necesita leer el recurso

Pendiente

Ultimas consideraciones
Pendiente

Referencia:
http://www.thinkplexx.com/
http://docs.oracle.com/javase
http://docs.oracle.com/javase/7