Passagem de parâmetros em chamadas de outra classe com main

15 respostas
T

Olá, pessoal. O meu novo problema é o seguinte:
preciso executar este trecho de código abaixo, que chama um outro
arquivo que tb contém um main, ou seja, é como se um executável
chamasse outro.

try {
    Class NovoClass = Class.forName("Novo");
    Class tipos[] = new Class[] { String[].class };
    Method metodoMain = NovoClass.getDeclaredMethod("main", tipos);
    Object parametros[] = new Object[1];
    String args[] = new String[0];
    args[0] = ("Objeto.txt");
    parametros[0] = args;
    metodoMain.invoke(null, parametros);
  } catch(Exception ex) {
  JOptionPane.showMessageDialog(this,ex);
}

O erro retornado é o seguinte: java.lang.ArrayIndexOutOfBoundsException.

Quando eu não passo parâmetros, ou seja, quando args.length é igual
a zero, tudo funciona legal. Já testei o código que recebe o nome do
arquivo por parâmetro em DOS e tb funcionou. O problema está nessa
passagem de parâmetro.

Não tenho idéia do que pode ser. :oops:

15 Respostas

mlopes

Tente :

String args[] = new String[1];

[]'s

T

Coloquei
String args[] = new String[1] e deu um erro do tipo:
java.lang.reflect.InvocationTargetException

mlopes

Ola,

Esse erro significa que exite algo de errado no método main da sua classe Novo.

Coloque:

} catch(Exception ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(this,ex);
}

E então copie aqui o erro para que a gente possa te ajudar.

[]'s

Elvis.The.Pelvis

InvocationTargetException é lançada quando o método que sofreu reflexão lança uma exceção. Seu método main está lançando alguma exceção.

T

Pois é, o que eu não entendo é o seguinte:
se eu eliminar a passagem de parâmetros,
a linha de código args[0] = “nome do arquivo” ,
a outra classe funciona normalmente, porque ela tb recebe
entrada de dados direto do teclado, como no DOS, e não dá erro desse
jeito.

Eu acredito e tenho ceretza que o erro está nessa passagem de
parâmetros e como recebi esta instrução de outra pessoa, não sei o que
pode ser.

Já procurei instruções na net e não encontrei nada que pudesse resolver.

HELPE ME!!!

dukejeffrie

Mas é exatamente o que o Elvis falou.

por acaso seu método main interno, vamos chamá-lo assim, lança exceção? Tente declará-lo assim:

public ... main(...) throws Exception {
  try {
   ...
  }
  catch (Exception e) {
    System.out.println("Exception no NovoClass.main(): " + e.getMessage());
    throw e;
  }
}

Desse jeito dá pra descobrir se o pau foi aí. Aliás, lançar qq exception é trash, mantenha as exceptions discriminadas sempre.

ArrayIndexOutOfBounds pode significar que o seu primeiro parâmetro (args[0]) contém uma string nula, vazia, sei lá, o que não parece lógico e absolutamente nunca aconteceria numa chamada normal.

Vc pode pegar a causa da InvocationTargetException() com o método getCause();

Mas to achando estrando essa variavel args[]. Você não precisa dela, pode fazer assim:

Object parametros[] = new String[1];
parametros[0] = "Objeto.txt";

[]s do duke!

mlopes

Ola,

Eu fiz um pequeno teste, talvez ajude.

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Caller {

	public static void main(String[] args) 
	{
		try {
			Class called = Class.forName("Called");
			Class[] types = new Class[] {String[].class};
			Method mainMethod = called.getDeclaredMethod("main", types);
			Object[] parameters = new Object[1];
			String[] arguments = new String[1];
			arguments[0] = "First parameter";
			parameters[0] = arguments;
			mainMethod.invoke(null, parameters);
		} catch (InvocationTargetException itex) {
			itex.getTargetException().printStackTrace();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
}

Agora o alvo:

public class Called {

	public static void main(String[] args) 
	{
		if (args.length > 0) {
			System.out.println("Called main with args[0] = " + args[0]);
		} else {
			throw new IllegalArgumentException("Invalid argument passed! Arguments length is 0");
		}
	}
}

[]'s

dukejeffrie

hehehe… getTargetException(), e não getCause()… : )

T

Olá, pessoal.

Desculpe-me mlopes, mas o trecho de código que a princípio vc me
mandou, funionou. O que não percebi é que depois gerava um outro erro.
Na verdade é o seguinte. Estou fazendo um ambiente de apredizagem de
algoritmos (Projeto de Pesquisa pela faculdade) que deve compilar o que
o usuário escreve (a segunda classe que eu chamo é o compilador).
Quando eu compilo a primeira vez, beleza! Porém, depois dá o seguinte erro:

“Second call to constructor of static parser. You must either use
ReInit() or set the JavaCC option Static to false during parser generation.”

Vocês podem me ajudar?

mlopes

Ola,

Não sei quais ferramentas vc está usando, mas a mensagem é clara. Vc deve checar se o Parser já foi inicializado, se já foi, ao invés de criar um novo, chame o método reInit. Se é que vc quer usar o Parser como sigleton. Se não, atribua falso. à essa opção do static.

A propósito, qual parser vc está usando ? Eu usei o JLex a muito tempo atrás.

[]'s

T

Olah…
Eu estou usando o gerador JavaCC. Ele gera tanto o analisador léxico
quanto o sintático. Agora estou implementando o analisador semântico,
que é a parte mais chatinha…

Mas voltando ao nosso assunto, como assim atribuir falso no static?
Não seria melhor eu destruir a classe depois que eu já utilizei? Pois o erro
é pq estou, no caso, chamando duas vezes o construtor.

[]'s,

mlopes

Bom,

Acredito que vc usa algo do tipo parser = TheParser(java.io.InputStream stream) . Vc deve então sempre checar se o seu parser é null. Se não for, chame TheParser.ReInit(java.io.InputStream stream).

Como eu não conheço bem o Javacc, não posso ajudar muito mais do q isso. Espero que funcione.

[]'s

T

Pois é, no JavaCC é diferente…
Você sabe como chamar um procedimento de uma classe já
instanciada?

O código a seguir não funciona!!! :cry:

try {
   Class tipos[] = new Class[] { String[].class };              
   Object parametros[] = new Object[1];
   String args[] = new String[1];
   args[0] = "objeto.txt";
   parametros[0] = args;  

   if (compilou == false) {
        Class NovoClass = Class.forName("Novo");
        Method metodoMain = NovoClass.getDeclaredMethod("main", tipos);  
        metodoMain.invoke(null,parametros);
        compilou = true;
   } else {
        Method metodoReInit = NovoClass.getDeclaredMethod("ReInit", tipos);
        metodoReInit.invoke(null,parametros); 
   }            
} catch(Exception ex) {
        JOptionPane.showMessageDialog(this, ex);
}
dukejeffrie

Eu acredito que, ainda mais por vc estar gerando código, vc deveria usar um parser dinâmico (ou seja, setar, no JavaCC, a opção para static parser como false).

O target do ant que chama o javacc tem a opção static = true | false | yes | no

No Google Groups, achei uma thread com um cara que teve exatamente o mesmo problema que você. Um outro respondeu o seguinte:

Tomara que isso resolva!!

[]s

T

Olá,

Consegui resolver meu problema. Um pouquinho diferente da instrução,
mas a idéia foi a mesma.

Eu tinha que gerar o arquivo do javacc com a opção STATIC = false, né?
Só que a maneira de fazer isso era compilar assim: javacc -NOSTATIC NomeDoArquivo.jj
(encontrei esta opção no código que vem com o JavaCC).

Obrigada pela ajuda pessoal, mais uma vez.

[]'s,

Criado 10 de março de 2003
Ultima resposta 19 de mar. de 2003
Respostas 15
Participantes 4