para que sirve settitle en java
Se está escapando esto en advertencia de constructor (10)
Digamos que originalmente tenía una clase como esta que se usaba como un ActionListener y por lo tanto termina llamando a addActionListener (this) que genera la advertencia.
private class CloseWindow extends JFrame implements ActionListener {
public CloseWindow(String e) {
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setLayout(new BorderLayout());
JButton exitButton = new JButton("Close");
exitButton.addActionListener(this);
add(exitButton, BorderLayout.SOUTH);
}
@Override
public void actionPerformed(ActionEvent e) {
String actionCommand = e.getActionCommand();
if(actionCommand.equals("Close")) {
dispose();
}
}
}
Como mencionó @Colin Hebert, podrías separar el ActionListener en su propia clase. Por supuesto, esto requeriría una referencia al JFrame al que desea llamar .dispose (). Si prefiere no llenar su espacio de nombre de variable, y quiere usar el ActionListener para múltiples JFrames, puede hacerlo con getSource () para recuperar el botón seguido de una cadena de llamadas de getParent () a recupera la Clase que extiende JFrame y luego llama a getSuperclass para asegurarte de que sea un JFrame.
private class CloseWindow extends JFrame {
public CloseWindow(String e) {
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setLayout(new BorderLayout());
JButton exitButton = new JButton("Close");
exitButton.addActionListener(new ExitListener());
add(exitButton, BorderLayout.SOUTH);
}
}
private class ExitListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String actionCommand = e.getActionCommand();
JButton sourceButton = (JButton)e.getSource();
Component frameCheck = sourceButton;
int i = 0;
String frameTest = "null";
Class<?> c;
while(!frameTest.equals("javax.swing.JFrame")) {
frameCheck = frameCheck.getParent();
c = frameCheck.getClass();
frameTest = c.getSuperclass().getName().toString();
}
JFrame frame = (JFrame)frameCheck;
if(actionCommand.equals("Close")) {
frame.dispose();
}
}
}
El código anterior funcionará para cualquier botón que sea un niño en cualquier nivel de una clase que extienda JFrame. Obviamente, si su objeto solo es un JFrame, solo es cuestión de verificar esa clase directamente en lugar de verificar la súper clase.
En última instancia, al usar este método obtendrás una referencia a algo como esto: MainClass $ CloseWindow que tiene el JFrame de superclase y luego estás lanzando esa referencia a JFrame y disponiéndolo.
Me gustaría evitar (la mayoría de) las advertencias de Netbeans 6.9.1, y tengo un problema con la advertencia ''Leaking this in constructor''
.
Entiendo el problema, llamar a un método en el constructor y pasar " this
" es peligroso, ya que " this
" puede no haberse inicializado por completo.
Fue fácil arreglar la advertencia en mis clases singleton, porque el constructor es privado y solo se llama desde la misma clase.
Código antiguo (simplificado):
private Singleton() {
...
addWindowFocusListener(this);
}
public static Singleton getInstance() {
...
instance = new Singleton();
...
}
Nuevo código (simplificado):
private Singleton() {
...
}
public static Singleton getInstance() {
...
instance = new Singleton();
addWindowFocusListener( instance );
...
}
Esta solución no funciona si el constructor es público y se puede llamar desde otras clases. ¿Cómo es posible arreglar el siguiente código?
public class MyClass {
...
List<MyClass> instances = new ArrayList<MyClass>();
...
public MyClass() {
...
instances.add(this);
}
}
Por supuesto, quiero una solución que no requiera modificar todos mis códigos usando esta clase (llamando a un método init, por ejemplo).
Envuelve this
entre corchetes. Netbeans ignora algunos errores por defecto si están en sub declaraciones.
public MyClass() {
...
instances.add((this));
}
https://.com/a/8357990
Este es un buen caso de que una fábrica que creó instancias de su clase sería útil. Si una fábrica fuera responsable de crear instancias de su clase, entonces tendría una ubicación centralizada donde se llama al constructor, y sería trivial agregar un método init()
requerido a su código.
Con respecto a su solución inmediata, le sugiero que mueva todas las llamadas que filtren this
a la última línea de su constructor, y luego suprímalas con una anotación una vez que haya "probado" que es seguro hacerlo.
En IntelliJ IDEA, puede suprimir esta advertencia con el siguiente comentario justo encima de la línea:
//noinspection ThisEscapedInObjectConstruction
La anotación @SuppressWarnings ("LeakingThisInConstructor") se aplica solo a la clase y no al propio constructor.
Solusion Sugeriría: crear el método privado init () {/ * usar esto aquí * /} y llamarlo desde el constructor. Los NetBeans no lo advertirán.
Las mejores opciones que tienes:
- Extraiga su parte
WindowFocusListener
en otra clase (también podría ser interna o anónima). La mejor solución, de esta forma cada clase tiene un propósito específico. - Ignora el mensaje de advertencia.
Usar un singleton como solución alternativa para un constructor con fugas no es realmente eficiente.
No hay necesidad de una clase de oyente separada.
public class Singleton implements WindowFocusListener {
private Singleton() {
...
}
private void init() {
addWindowFocusListener(this);
}
public static Singleton getInstance() {
...
if(instance != null) {
instance = new Singleton();
instance.init();
}
...
}
}
Uno puede escribir:
addWindowFocusListener(Singleton.this);
Esto evitará que NB muestre la advertencia.
Usar una clase anidada (como sugiere Colin) es probablemente su mejor opción. Aquí está el pseudocódigo:
private Singleton() {
...
}
public static Singleton getInstance() {
...
instance = new Singleton();
addWindowFocusListener( new MyListener() );
...
private class MyListener implements WindowFocusListener {
...
}
}
Ya que te aseguras de poner tus instances.add(this)
al final del constructor , en mi humilde opinión, debes estar seguro de decirle al compilador que simplemente suprima la advertencia (*) . Una advertencia, por su naturaleza, no necesariamente significa que hay algo mal, solo requiere su atención.
Si sabe lo que está haciendo, puede usar una anotación @SuppressWarnings
. Como Terrel mencionó en sus comentarios, la siguiente anotación lo hace a partir de NetBeans 6.9.1:
@SuppressWarnings("LeakingThisInConstructor")
(*) Actualización: Como Isthar y Sergey señalaron que hay casos en los que el código de constructor "con fuga" puede parecer perfectamente seguro (como en su pregunta) y sin embargo no lo es. ¿Hay más lectores que puedan aprobar esto? Estoy considerando eliminar esta respuesta por los motivos mencionados.
[Comentario de chiccodoro: una explicación de por qué / cuando se filtra this
puede causar problemas, incluso si la declaración de fuga se coloca al final en el constructor:]
La semántica de campo final es diferente de la semántica de campo ''normal''. Un ejemplo,
Jugamos un juego en red. Permite hacer que un objeto del juego recupere datos de la red y un objeto del jugador que escucha eventos del juego para actuar en consecuencia. El objeto del juego oculta todos los detalles de la red, el jugador solo está interesado en los eventos:
import java.util.*;
import java.util.concurrent.Executors;
public class FinalSemantics {
public interface Listener {
public void someEvent();
}
public static class Player implements Listener {
final String name;
public Player(Game game) {
name = "Player "+System.currentTimeMillis();
game.addListener(this);//Warning leaking ''this''!
}
@Override
public void someEvent() {
System.out.println(name+" sees event!");
}
}
public static class Game {
private List<Listener> listeners;
public Game() {
listeners = new ArrayList<Listener>();
}
public void start() {
Executors.newFixedThreadPool(1).execute(new Runnable(){
@Override
public void run() {
for(;;) {
try {
//Listen to game server over network
Thread.sleep(1000); //<- think blocking read
synchronized (Game.this) {
for (Listener l : listeners) {
l.someEvent();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
public synchronized void addListener(Listener l) {
listeners.add(l);
}
}
public static void main(String[] args) throws InterruptedException {
Game game = new Game();
game.start();
Thread.sleep(1000);
//Someone joins the game
new Player(game);
}
}
//Code runs, won''t terminate and will probably never show the flaw.
Parece todo bien: el acceso a la lista está sincronizado correctamente. El error es que este ejemplo filtra el Player.this a Game, que está ejecutando un hilo.
Final es bastante scary :
... los compiladores tienen una gran libertad para mover las lecturas de los campos finales a través de las barreras de sincronización ...
Esto prácticamente derrota a todas las sincronizaciones apropiadas. Pero afortunadamente
Se garantiza que un hilo que solo puede ver una referencia a un objeto después de que ese objeto se haya inicializado por completo vea los valores inicializados correctamente para los campos
final
ese objeto.
En el ejemplo, el constructor escribe la referencia de los objetos a la lista. (Y por lo tanto, aún no se ha inicializado completamente, dado que el constructor no finalizó). Después de la escritura, el constructor aún no está terminado. Simplemente tiene que regresar del constructor, pero supongamos que aún no. ¡Ahora el ejecutor podría hacer su trabajo y transmitir eventos a todos los oyentes, incluido el objeto de jugador aún no inicializado! ¡El campo final del jugador (nombre) no se puede escribir, y dará como resultado la impresión del null sees event!
.