I'm trying the sample code from [Core java programming] volume 2, chapter 8, with tiny modification. First. I've build a intellij project, with a simple class and "f()" function, already compiled:
public class BasicTypes {
public void f() {
System.out.println("BasicTypes.f()");
}
}
Then I have 2 classes to load class:
class StringBuilderJavaSource extends SimpleJavaFileObject {
private StringBuilder code;
public StringBuilderJavaSource(String className) {
super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension),
Kind.SOURCE);
code = new StringBuilder();
}
#Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
System.out.println(code);
return code;
}
public void append(String s) {
code.append(s);
code.append('\n');
}
}
class ByteArrayJavaClass extends SimpleJavaFileObject {
private ByteArrayOutputStream stream;
public ByteArrayJavaClass(String className) {
super(URI.create("bytes:///" + className), Kind.CLASS);
stream = new ByteArrayOutputStream();
}
#Override
public OutputStream openOutputStream() {
return stream;
}
public byte[] getBytes() {
return stream.toByteArray();
}
}
And then the main function:
public static void main(String args[]) {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
final List<ByteArrayJavaClass> classFileObjects = new ArrayList<>();
DiagnosticCollector<JavaFileObject> diagnosticCollector = new DiagnosticCollector<>();
JavaFileManager fileManager = compiler.getStandardFileManager(diagnosticCollector, null, null);
fileManager = new ForwardingJavaFileManager<JavaFileManager>(fileManager) {
#Override
public JavaFileObject getJavaFileForOutput(
Location location,
final String className,
JavaFileObject.Kind kind,
FileObject sibling) throws IOException {
System.out.println("Enter getJavaFileForOutput");
if (className.startsWith("x.")) {
ByteArrayJavaClass fileObject = new ByteArrayJavaClass(className);
classFileObjects.add(fileObject);
System.out.println("Enter x");
return fileObject;
} else {
System.out.println("Enter others");
return super.getJavaFileForOutput(location, className, kind, sibling);
}
}
};
StringBuilderJavaSource source = new StringBuilderJavaSource("myFirstClass");
source.append("package x;");
source.append("public class myFirstClass extends " + "BasicTypes" + " {");
source.append(" public void f(){System.out.println(\"myFirstClass.f()\");}");
source.append("}");
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnosticCollector,
null, null, Arrays.asList(source));
Boolean result = task.call();
if (!result) {
System.out.println("Compilation failed");
System.exit(1);
}
}
The program fails to compile and prints:
package x;
public class myFirstClass extends BasicTypes {
public void f(){System.out.println("myFirstClass.f()");}
}
Compilation failed
Seems the failure doesn't have enough information for me to do tourble-shooting.
So where did I get wrong in my program, and how to fix it?
Thanks a lot.
Related
I'm writing a fairly simple program, which needs to save some simple data between runs. This data is defined by UserData, outlined below:
public class UserData implements Serializable {
/**
*
*/
private static final long serialVersionUID = -3542558265070011448L;
public static ArrayList<String> projectList;
public static ArrayList<Bill> billList;
public static String userName;
public static String userEmail;
public UserData() {
}
public UserData(String name, String email) {
super();
userName = name;
userEmail = email;
projectList = new ArrayList<String>();
billList = new ArrayList<Bill>();
}
public String getUserName() {
return userName;
}
public String getUserEmail() {
return userEmail;
}
public ArrayList<Bill> getBillList() {
return billList;
}
public ArrayList<String> getProjectList() {
return projectList;
}
public void setBillList(Bill theBill) {
billList.add(theBill);
}
public void setProjectList(String projectName) {
projectList.add(projectName);
}
}
I Then have a class which handles serializing/deserializing of this data and it's instance to a file, with the various calls done directly or indirectly by events in a separate Gui Class. This is it:
public class FileHandler implements Serializable {
/**
*
*/
private static final long serialVersionUID = 473118590700911358L;
private static JFileChooser fileChooser;
public UserData myUserData;
public FileHandler() throws ClassNotFoundException, IOException {
fileChooser = new JFileChooser();
initData();
}
public FileHandler(UserData newUser) {
fileChooser = new JFileChooser();
myUserData = newUser;
System.out.println("Entered User: " + myUserData.getUserName());
System.out.println("Entered User: " + myUserData.getUserEmail());
}
private void createProgramData() throws FileNotFoundException, IOException {
FileOutputStream fileOut = new FileOutputStream("data\\ProgramData.diy");
ObjectOutputStream encoderp = new ObjectOutputStream(fileOut);
System.out.println("createProgramData: " + myUserData.getUserName());
System.out.println("createProgramData: "+ myUserData.getUserEmail());
encoderp.writeObject(myUserData);
encoderp.close();
fileOut.close();
}
public void exportData() throws FileNotFoundException, IOException {
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
final int selectedFile = fileChooser.showOpenDialog(null);
ObjectOutputStream encodere = null;
if (selectedFile == JFileChooser.APPROVE_OPTION) {
final File selectedPath = fileChooser.getSelectedFile();
FileOutputStream fileOut = new FileOutputStream(selectedPath + "\\UserData.diy");
encodere = new ObjectOutputStream(fileOut);
System.out.println("Writing Data: " + myUserData.getUserName());
System.out.println("Writing Data: " + myUserData.getUserEmail());
encodere.writeObject(myUserData);
encodere.close();
fileOut.close();
}
}
public void importData() throws ClassNotFoundException, IOException {
fileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
final int selectedFile = fileChooser.showSaveDialog(null);
ObjectInputStream decoderim = null;
if (selectedFile == JFileChooser.APPROVE_OPTION) {
final File selectedPath = fileChooser.getSelectedFile();
FileInputStream fileIn = new FileInputStream(selectedPath);
decoderim = new ObjectInputStream(fileIn);
myUserData = (UserData)decoderim.readObject();
decoderim.close();
fileIn.close();
System.out.println("importing Data: " + myUserData.getUserEmail());
System.out.println("importing Data: " + myUserData.getUserName());
}
}
private void initData() throws IOException, ClassNotFoundException {
FileInputStream fileIn = new FileInputStream("data\\ProgramData.diy");
ObjectInputStream decoderi = new ObjectInputStream(fileIn);
myUserData = (UserData)decoderi.readObject();
decoderi.close();
fileIn.close();
System.out.println("initializing Data: " + myUserData.getUserName());
System.out.println("Initializing Data: " + myUserData.getUserEmail());
}
public UserData getUserData() {
return myUserData;
}
A problem I'm having with the ObjectInputStream and possibly ObjectOutputStream seems to be that when I serialize UserData, exit my program, and then re-enter and try to import that file, the instance of UserData remains unchanged. I can't seem to figure out what I'm missing. Even pointing out something I've overlooked helps.
UserData only has static fields, and static fields aren't serialized. From the look of your code they should all be instance members. Don't make anything static unless you know exactly why you are doing so.
I'm trying to load classes from tree structure similar to JavaEE web application. So I have directory which contains compiled classes (/classes) and sibling directory with libraries (/lib). In classes package structure I have compiled class com.test.Test.class with simple logic:
package com.test;
import org.json.JSONException;
import org.json.JSONObject;
import com.test.GameObjectState;
public class Test extends Thread {
#Override
public void run() {
JSONObject json = new JSONObject();
try {
json.put("state", GameObjectState.REMOVED);
} catch (JSONException e) {
e.printStackTrace();
}
System.out.println(json.toString());
}
}
And here's my main:
ClassLoader classLoader = ClassLoaderFactory.createClassLoader(repository);
Class<?> testClass = classLoader.loadClass("com.test.Test");
Thread t = (Thread) testClass.newInstance();
t.start();
My ClassLoader implementation follows the delegation model. During context init finally JSONObject & JSONException will be scanned and found in lib/java-json.jar (matching corresponding JarEntry binary name inside). When JarEntry found - creates InputStream to load data in buffer to define class.
JSONException loaded successfully while JSONObject failed on ClassFormatError. Magic is that I've extracted JSONObject in /classes directory manually from java-json.jar and no ClassFormatError has been thrown, JSONObject created and output printed successfully. Probably should note that JSONObject has inner/nested classes compiled in library.
And here's my classloader
public class WebAppClassLoader extends URLClassLoader {
private static final String CLASS_FILE_SUFFIX = ".class";
private static final String JAR_FILE_SUFFIX = ".jar";
private static final String CLASS_NOT_FOUND = "Class %s not found";
private File classesDirectory;
private Map<String, Class<?>> classes;
public WebAppClassLoader(File classesDirectory, URL[] urls) {
super(urls);
this.classesDirectory = classesDirectory;
this.classes = new ConcurrentHashMap<String, Class<?>>();
}
public static WebAppClassLoader newInstance(File classesDirectory, File libDirectory) throws IOException {
File[] jars = libDirectory.listFiles(new JarFilter());
Set<URL> jarUrls = new HashSet<URL>();
for(File jar : jars) {
jarUrls.add(jar.toURI().toURL());
}
return new WebAppClassLoader(classesDirectory, jarUrls.toArray(new URL[jarUrls.size()]));
}
protected static class DirectoryFilter implements FileFilter {
#Override
public boolean accept(File pathname) {
return pathname.isDirectory();
}
}
protected static class ClassFilter implements FileFilter {
#Override
public boolean accept(File pathname) {
return pathname.getName().endsWith(CLASS_FILE_SUFFIX);
}
}
protected static class JarFilter implements FileFilter {
#Override
public boolean accept(File pathname) {
return pathname.getName().endsWith(JAR_FILE_SUFFIX);
}
}
#Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
Class<?> result = null;
byte[] buffer = null;
try {
buffer = scanClasses(classesDirectory, asPathName(name));
if(buffer == null) {
buffer = scanLib(asPathName(name).replace('\\', '/'));
}
if(buffer != null) {
result = defineClass(name, buffer, 0, buffer.length);
classes.put(name, result);
}
} catch(IOException e) {
e.printStackTrace();
}
if(result == null) {
String error = String.format(CLASS_NOT_FOUND, name);
throw new ClassNotFoundException(error);
}
return result;
}
private byte[] scanClasses(File file, String path) throws IOException {
byte[] result = null;
File[] directories = file.listFiles(new DirectoryFilter());
File[] classes = file.listFiles(new ClassFilter());
for(File classFile : classes) {
if(classFile.getAbsolutePath().endsWith(path)) {
InputStream input = new FileInputStream(classFile);
input.read(result = new byte[input.available()]);
input.close();
break;
}
}
if(result == null) {
for(File directory : directories) {
result = scanClasses(directory, path);
if(result != null) {
break;
}
}
}
return result;
}
private byte[] scanLib(String path) throws IOException {
byte[] result = null;
for(URL url : getURLs()) urlLoop:{
File file = new File(url.getFile());
JarFile jarFile = new JarFile(file);
try {
Enumeration<JarEntry> entries = jarFile.entries();
while(entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if(entry.getName().endsWith(path)) {
InputStream input = jarFile.getInputStream(entry);
input.read(result = new byte[input.available()]);
break urlLoop;
}
}
}finally {
jarFile.close();
}
}
return result;
}
#Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
Class<?> result = null;
if(classes.containsKey(name)) {
result = classes.get(name);
}else{
result = super.loadClass(name);
}
return result;
}
private static String asPathName(String binaryName) {
return binaryName.replace('.', '\\').concat(CLASS_FILE_SUFFIX);
}
}
Thanks
I need to get the line numbers a specific method is invoked in a .class file.
I took a look at How can I find all the methods that call a given method in Java? It returns the methods that call a method but I need the line numbers in the caller methods, as well.
I solved it by manipulating the code on that link a little
import java.io.InputStream;
import org.objectweb.asm.*;
import org.objectweb.asm.commons.*;
public class App{
public static void main( String[] args ) {
try {
Test test = new Test();
test.findCallers();
}catch (Exception e){
e.printStackTrace();
}
}
}
class Test {
private String targetClass;
private Method targetMethod;
private AppClassVisitor cv;
class AppMethodVisitor extends MethodVisitor {
boolean callsTarget;
int line;
public AppMethodVisitor() {
super(Opcodes.ASM5);
}
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
if (owner.equals("Fibonacci") && name.equals("join") && desc.equals("()V")) {
callsTarget = true;
System.out.println("Function join called on " + this.line);
}
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
public void visitCode() {
callsTarget = false;
}
public void visitLineNumber(int line, Label start) {
this.line = line;
}
public void visitEnd() {
if (callsTarget){
System.out.println(cv.className + cv.methodName + cv.methodDesc + line);
}
}
}
class AppClassVisitor extends ClassVisitor {
private AppMethodVisitor mv = new AppMethodVisitor();
public String className;
public String methodName;
public String methodDesc;
public AppClassVisitor() {
super(Opcodes.ASM5);
}
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
className = name;
}
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
methodName = name;
methodDesc = desc;
return mv;
}
}
public void findCallers() throws Exception {
InputStream stream = App.class.getResourceAsStream("Fibonacci.class");
ClassReader reader = new ClassReader(stream);
cv = new AppClassVisitor();
reader.accept(cv, 0);
stream.close();
}
}
Fibonacci.java content:
public class Fibonacci extends Thread{
int n;
int result;
public Fibonacci(int n){
this.n = n;
}
public void run(){
if((n == 0) || (n == 1)){
result = 1;
}else{
Fibonacci f1 = new Fibonacci(n - 1);
Fibonacci f2 = new Fibonacci(n - 2);
f1.start();
f2.start();
try{
f1.join();
f2.join();
}catch(InterruptedException e){
e.printStackTrace();
}
result = f1.getResult() + f2.getResult();
}
}
public int getResult(){
return result;
}
public static void main(String[] args) {
Fibonacci f1 = new Fibonacci(5);
f1.start();
try{
f1.join();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Answer is " + f1.getResult());
}
}
Has anyone an idea about what is wrong with my attempt to call a method from a C# dll in my Java code?
Here is my example:
Java code:
public class CsDllHandler {
public interface IKeywordRun extends Library {
public String KeywordRun(String action, String xpath, String inputData,
String verifyData);
}
private static IKeywordRun jnaInstance = null;
public void runDllMethod(String action, String xpath, String inputData,
String verifyData) {
NativeLibrary.addSearchPath(${projectDllName},
"${projectPath}/bin/x64/Debug");
jnaInstance = (IKeywordRun) Native.loadLibrary(
${projectDllName}, IKeywordRun.class);
String csResult = jnaInstance.KeywordRun(action, xpath, inputData,
verifyData);
System.out.println(csResult);
}
}
And in C#:
[RGiesecke.DllExport.DllExport]
public static string KeywordRun(string action, string xpath, string inputData, string verifyData) {
return "C# here";
}
The Unmanaged Exports nuget should be enough for me to call this method (in theory) but I have some strange error:
Exception in thread "main" java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokePointer(Native Method)
at com.sun.jna.Function.invokePointer(Function.java:470)
at com.sun.jna.Function.invokeString(Function.java:651)
at com.sun.jna.Function.invoke(Function.java:395)
at com.sun.jna.Function.invoke(Function.java:315)
at com.sun.jna.Library$Handler.invoke(Library.java:212)
at com.sun.proxy.$Proxy0.KeywordRun(Unknown Source)
at auto.test.keywords.utils.CsDllHandler.runDllMethod(CsDllHandler.java:34)
at auto.test.keywords.runner.MainClass.main(MainClass.java:24)
Well, after another day of research and "trial and error" I have found the cause of my problem and a solution.
The cause was that my C# dll had a dependency on log4net.dll. For running a static method from a standalone C# dll the code from the question is all you need.
The solution for using C# dll with dependencies is to create another dll with no dependency and to load the original dll in this adapter with reflection. In Java you should load the adapter dll with jna and call any exported method. I was able not only to execute methods from the adapter but also to configure log4net with reflection and Java
Here is my code:
(C#)
public class CSharpDllHandler {
private static Logger log = Logger.getLogger(CSharpDllHandler.class);
public interface IFrameworkAdapter extends Library {
public String runKeyword(String action, String xpath, String inputData,
String verifyData);
public String configureLog4net(String log4netConfigPath);
public String loadAssemblies(String frameworkDllPath,
String log4netDllPath);
}
private static IFrameworkAdapter jnaAdapterInstance = null;
private String jnaSearchPath = null;
public CSharpDllHandler(String searchPath) {
this.jnaSearchPath = searchPath;
// add to JNA search path
System.setProperty("jna.library.path", jnaSearchPath);
// load attempt
jnaAdapterInstance = (IFrameworkAdapter) Native.loadLibrary(
"FrameworkAdapter", IFrameworkAdapter.class);
}
public String loadAssemblies(String frameworkDllPath, String log4netDllPath) {
String csResult = jnaAdapterInstance.loadAssemblies(frameworkDllPath,
log4netDllPath);
log.debug(csResult);
return csResult;
}
public String runKeyword(String action, String xpath, String inputData,
String verifyData) {
String csResult = jnaAdapterInstance.runKeyword(action, xpath,
inputData, verifyData);
log.debug(csResult);
return csResult;
}
public String configureLogging(String log4netConfigPath) {
String csResult = jnaAdapterInstance
.configureLog4net(log4netConfigPath);
log.debug(csResult);
return csResult;
}
public String getJnaSearchPath() {
return jnaSearchPath;
}
}
In the main method just use something like this:
CSharpDllHandler dllHandler = new CSharpDllHandler(
${yourFrameworkAdapterDllLocation});
dllHandler.loadAssemblies(
${yourOriginalDllPath},${pathToTheUsedLog4netDllFile});
dllHandler.configureLogging(${log4net.config file path});
dllHandler.runKeyword("JAVA Action", "JAVA Xpath", "JAVA INPUT",
"JAVA VERIFY");
dllHandler.runKeyword("JAVA Action2", "JAVA Xpath2", "JAVA INPUT2",
"JAVA VERIFY2");
In C# I have the desired methods on the original dll:
public static string KeywordRun(string action, string xpath, string inputData, string verifyData) {
log.Debug("Action = " + action);
log.Debug("Xpath = " + xpath);
log.Debug("InputData = " + inputData);
log.Debug("VerifyData = " + verifyData);
return "C# UserActions result: "+ action+" "+xpath+" "+inputData+" "+verifyData;
}
and all the magic is in the DLL Adapter:
namespace FrameworkAdapter {
[ComVisible(true)]
public class FwAdapter {
private const String OK="OK";
private const String frameworkEntryClassName = "${nameOfTheDllClass with method to run }";
private const String log4netConfiguratorClassName = "log4net.Config.XmlConfigurator";
private static Assembly frameworkDll = null;
private static Type frameworkEntryClass = null;
private static MethodInfo keywordRunMethod = null;
private static Assembly logDll = null;
private static Type logEntryClass = null;
private static MethodInfo logConfigureMethod = null;
private static String errorMessage = "OK";
[RGiesecke.DllExport.DllExport]
public static string loadAssemblies(string frameworkDllPath, string log4netDllPath) {
try {
errorMessage = LoadFrameworkDll(frameworkDllPath, frameworkEntryClassName);
LoadFrameworkMethods("KeywordRun", "Setup", "TearDown");
errorMessage = LoadLogAssembly(log4netDllPath, log4netConfiguratorClassName);
if (errorMessage.CompareTo(OK) == 0)
errorMessage = LoadLogMethods("Configure");
}
catch (Exception e) {
return e.Message;
}
return errorMessage;
}
[RGiesecke.DllExport.DllExport]
public static string configureLog4net(string log4netConfigPath) {
if (errorMessage.CompareTo("OK") == 0) {
StringBuilder sb = new StringBuilder();
sb.AppendLine("Try to configure Log4Net");
try {
FileInfo logConfig = new FileInfo(log4netConfigPath);
logConfigureMethod.Invoke(null, new object[] { logConfig });
sb.AppendLine("Log4Net configured");
}
catch (Exception e) {
sb.AppendLine(e.InnerException.Message);
}
return sb.ToString();
}
return errorMessage;
}
[RGiesecke.DllExport.DllExport]
public static string runKeyword(string action, string xpath, string inputData, string verifyData) {
StringBuilder sb = new StringBuilder();
object result = null;
try {
result = keywordRunMethod.Invoke(null, new object[] { action, xpath, inputData, verifyData });
sb.AppendLine(result.ToString());
}
catch (Exception e) {
sb.AppendLine(e.InnerException.Message);
}
return sb.ToString();
}
private static String LoadFrameworkDll(String dllFolderPath, String entryClassName) {
try {
frameworkDll = Assembly.LoadFrom(dllFolderPath);
Type[] dllTypes = frameworkDll.GetExportedTypes();
foreach (Type t in dllTypes)
if (t.FullName.Equals(entryClassName)) {
frameworkEntryClass = t;
break;
}
}
catch (Exception e) {
return e.InnerException.Message;
}
return OK;
}
private static String LoadLogAssembly(String dllFolderPath, String entryClassName) {
try {
logDll = Assembly.LoadFrom(dllFolderPath);
Type[] dllTypes = logDll.GetExportedTypes();
foreach (Type t in dllTypes)
if (t.FullName.Equals(entryClassName)) {
logEntryClass = t;
break;
}
}
catch (Exception e) {
return e.InnerException.Message;
}
return OK;
}
private static String LoadLogMethods(String logMethodName) {
try {
logConfigureMethod = logEntryClass.GetMethod(logMethodName, new Type[] { typeof(FileInfo) });
}
catch (Exception e) {
return e.Message;
}
return OK;
}
private static void LoadFrameworkMethods(String keywordRunName, String scenarioSetupName, String scenarioTearDownName) {
///TODO load the rest of the desired methods here
keywordRunMethod = frameworkEntryClass.GetMethod(keywordRunName);
}
}
}
Running this code will provide all the logged messages from the original C# DLL to the Java console output (and to a file if configured). In a similar way, we can load any other needed dll files for runtime.
Please forgive my [very probable wrong] way of doing things in C# with reflection, I'm new to this language.
My goal: save one ArrayList to a .dat file, after read this file and in the end print this array.
To save the ArrayList, "equipas" is one ArrayList< Equipa>, I use this function:
saveMyFile("Equipas.dat", (Object) equipas);
To read:
public static ArrayList<Equipa> readMyFile(String s){
ArrayList<Equipa> novo = new ArrayList<Equipa>();
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(s));
novo = (ArrayList<Equipa>) ois.readObject();
ois.close();
}
catch(IOException er) { System.out.println(er.getMessage()); }
catch(ClassNotFoundException er) { System.out.println(er.getMessage()); }
return novo;}
In this read function, I have one Compilation Warning: "…uses unchecked or unsafe operations. Recompile with - Xlint:unchecked for details."
To save:
public static void saveMyFile(String s, Object o)
{
try {
ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream(s));
oos.writeObject(o);
oos.flush();
oos.close();
}
catch(IOException e) { System.out.println(e.getMessage()); }
}
Finally, I want to print the ArrayList's info:
ArrayList<Equipa> cena = new ArrayList<Equipa>();
cena=(ArrayList<Equipa>) readMyFile("Equipas.dat");
for(Equipa e:cena)
e.toString();
Error when I try to run:
" writing aborted; java.io.NotSerializableException: Equipa"
Equipa havs the Serializable:
import java.util.*;
import java.io.*;
public class Equipa implements Serializable
{
private String nome;
private Carro carro;
private ArrayList<Piloto> pilotos;
private double tempoDecorrido;
private int pontos;
private boolean desistiu;
private int voltaDesistencia;
private Piloto piloto;
/**
* Constructor for objects of class Equipa
*/
public Equipa()
{
this.nome = "NA";
this.carro = null;
this.pilotos = new ArrayList<Piloto>();
this.tempoDecorrido = 0;
this.pontos = 0;
this.desistiu = false;
this.voltaDesistencia = 0;
this.piloto = null;
}
public Equipa(String nome, Carro carro, ArrayList<Piloto> pilotos)
{
this.nome = nome;
this.carro = carro;
//this.pilotos = new ArrayList<Piloto>(pilotos);
this.pilotos = pilotos;
this.tempoDecorrido = 0;
this.pontos = 0;
this.desistiu = false;
this.voltaDesistencia = 0;
//this.piloto = pilotos.get(0);
}
public Equipa (Equipa e)
{
this.nome = e.getNome();
this.carro = e.getCarro();
this.pilotos = e.getPilotos();
this.tempoDecorrido = e.getTempoDecorrido();
this.pontos = e.getPontos();
this.desistiu = e.getDesistiu();
this.voltaDesistencia = e.getVoltaDesistencia();
//this.piloto = e.getPiloto();
}
/** Getters */
public String getNome()
{
return this.nome;
}
public Carro getCarro()
{
return this.carro;
}
public ArrayList<Piloto> getPilotos()
{
return new ArrayList<Piloto>(this.pilotos);
}
public double getTempoDecorrido()
{
return this.tempoDecorrido;
}
public int getPontos()
{
return this.pontos;
}
public boolean getDesistiu()
{
return this.desistiu;
}
public int getVoltaDesistencia()
{
return this.voltaDesistencia;
}
public Piloto getPiloto()
{
return this.piloto;
}
/** Setters */
public void setNome(String nome)
{
this.nome = nome;
}
public void setCarro(Carro carro)
{
this.carro = carro;
}
public void setPilotos(ArrayList<Piloto> pilotos)
{
this.pilotos = new ArrayList<Piloto>(pilotos);
}
public void setTempoDecorrido(double tempoDecorrido)
{
this.tempoDecorrido = tempoDecorrido;
}
public void setPontos(int pontos)
{
this.pontos = pontos;
}
public void setDesistiu(boolean desistiu)
{
this.desistiu = desistiu;
}
public void setVoltaDesistencia(int voltaDesistencia)
{
this.voltaDesistencia = voltaDesistencia;
}
public void setPiloto(Piloto piloto)
{
this.piloto = piloto;
}
/** Outros Métodos */
public Equipa clone()
{
return new Equipa(this);
}
public boolean equals(Equipa e)
{
if(this.nome == e.getNome())
return true;
else
return false;
}
public String getStringPilotos()
{
String s = new String();
for(Piloto p: this.pilotos)
s = (s + ", " + p.getNome());
return s;
}
public String toString()
{
return new String("Nome da equipa: " + nome + "; Categoria do carro: " + carro.getClass().getName() + "; Marca e modelo: " + carro.getMarca() + " " + carro.getModelo() + "; Pilotos: " + getStringPilotos())+"\n";
}
Implementing Serializable means that serialization is permitted, but not necessarily that it is possible. For it to work, everything referenced by Equipa must also be either primitive or Serializable (and so on, recursively). Is this the case?
Warning in the read function is the result of generics in java. You won't be able to suppress it, unless you use #SuppressWarnings("unchecked") to ignore it.
If you are sure you are reading an ArrayList<Equipa>, you can ignore it without any problem.
With the Equipa code, I can try to point to the Serializable problem: make sure that Carro and Piloto classes are also Serializables. You can add the code of theses classes if you are not sure.
The only type-safer way would be do a custom serialization, using writeObject(OutputStream) and readObjectInputStream say on a class ArrayListOfEquipa maybe using Equipa[] (ArrayList.toArray()).
Not really attractive, if the warning would be the only reason.