i have this code:
File fileData = new File(this.getDataFolder(), "data.yml");
FileConfiguration data = YamlConfiguration.loadConfiguration(fileData);
data.options().copyDefaults(true);
try {
data.save(fileData);
} catch (IOException e) {
e.printStackTrace();
}
now my question is how i can do a instance of data in other class, i mean this is bukkit so i need that in another class i can execute the command data.save(fileData);
If you need that specific instance of FileConfiguration, the only way to have its reference in another class is using constructors, assuming the other class where you need this object is created in this class you could do something like so:
class YourClass{
File fileData;
FileConfiguration data;
#Override
void onEnable(){
fileData = new File(this.getDataFolder(), "data.yml");
data = YamlConfiguration.loadConfiguration(fileData);
data.options().copyDefaults(true);
try {
data.save(fileData);
} catch (IOException e) {
e.printStackTrace();
}
}
void theMethodWhereYouInstantiateTheOtherClass(){
OtherClass oc = new OtherClass();
}
}
And the the other class would look something like:
class OtherClass{
FileConfiguration data;
public OtherClass(FileConfiguration data){
this.data = data;
}
}
Related
I've created an Interface named "Writeable", and every class that implements it should override the method returnFilePath - which returns a String - a path to the correct file path related to that class.
for Example:
public class PatientRepository extends Observable implements Writeable,Readable{
private static final String filepath="src/files/patients.det";
...
#Override
public String returnFilePath() {
return filepath;
}
as you can see, this class also extends Observable. that class is observed by FileManager class:
public class FileManager implements Observer {
#Override
public void update(Observable o, Object arg) {
try (OutputStream fileOutputStream = new FileOutputStream(????);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream)){
objectOutputStream.writeObject(arg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
what i want to do is that in the FileOutputStream constructor i'll pass the correct file path, according to the Object i'm currently working on, but I can't get access to the returnFilePath() method i wrote.
what should i do to fix that?
All i had to do is casting:
public class FileManager implements Observer {
#Override
public void update(Observable o, Object arg) {
try (OutputStream fileOutputStream = new FileOutputStream( ((Writeable)o).returnFilePath());
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream)){
objectOutputStream.writeObject(arg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
I am beginning java, and started to play with serialization. I wonder if there is any way to write the deserialization function inside the class itself. Let me clarify what I mean: I can deserialize an object (i.e. from class Person) from within another class and it works:
public class Dummy{
...
public static void main(String args[])
{
...
Person father = null;
try {
FileInputStream load = new FileInputStream(saved_file);
ObjectInputStream in = new ObjectInputStream(load);
indiv = (Person) in.readObject();
in.close();
load.close();
} catch (...) { ... }
}
}
But, for being tidy, is it possible to move this inside the Person class as a function? For instance, to do something like this:
public class Person implements Serializable {
private boolean isOrphan = false;
private Person parent;
...
public void load(File saved_file) {
try {
FileInputStream load = new FileInputStream(saved_file);
ObjectInputStream in = new ObjectInputStream(load);
this = (Person) in.readObject(); // Error: cannot assign a value to final variabl this
in.close();
load.close();
} catch (...) { ... }
}
}
And then in the other class just call this:
public class Dummy{
...
public static void main(String args[])
{
...
Person father = null;
father.load(saved_file);
}
}
You can't call an instance method on an instance that doesn't exist yet. Even if your code could compile, you would get a NullPointerException because youĆ¹re calling a method on null.
Make your method static and make it return the deserialized instance. More generally, this is not a variable that you can assign, it's an immutable reference to an object.
public static Person load(File saved_file) {
try (FileInputStream load = new FileInputStream(saved_file);
ObjectInputStream in = new ObjectInputStream(load)) {
return (Person) in.readObject();
} catch (...) { ... }
}
public class Dummy {
public static void main(String args[]) {
Person father = Person.load(saved_file);
}
}
PS: I also added try-catch with resources instead of explicit close() because it's safer.
//Singleton
public class MainList implements Serializable {
private static MainList instance = new MainList();
private MainList() {}
public static MainList getInstance() {
return instance;
}
}
//Trying to deserialize..
public MainWindow() {
//Importing the latest version if it exists in path
MainList mainListObj = MainList.getInstance();
try {
FileInputStream fis = new FileInputStream(path);
ObjectInputStream oin = new ObjectInputStream(fis);
mainListObj = (MainList) oin.readObject(); //HERE//////
}
catch (Exception exc) {
return;
}
}
Singleton-Object of class MainList is serialized & can be found by path.
On the line //HERE/// object successfully deserializing to mainListObj,
BUT it's local..
How can I make it global? I think it could be solved by chanching getInstance method..somehow..
Your case is not singleton.
In your case, you can simply provide a setter.
static void setInstance(MainList newInstance) {
instance = newInstance;
}
MainList.setInstance(mainListObj);
Is there a way for me to get a super implementation directly through getContructor? I want to call the constructor on "this class or any superclass".
The scenario details are that I have a base class that builds its data using reflection but the data is coming in from an external file. The external loader has a lookup that checks to see if data exists for a particular class and all of that is wrapped into ImplementedCard, below.
This works fine (enough) and isn't directly related to the question aside from my needing to be able to create all of these instances starting from an ImplementedCard instance:
public class Card implements DeepCopyable<Card> {
protected ImplementedCardList.ImplementedCard implementedCard;
public Card() {
this.implementedCard = ImplementedCardList.getInstance().getCardForClass(this.getClass());
this.initFromImplementedCard(this.implementedCard);
}
public Card(ImplementedCardList.ImplementedCard implementedCard) {
this.implementedCard = implementedCard;
this.initFromImplementedCard(this.implementedCard);
}
public void initFromImplementedCard(ImplementedCardList.ImplementedCard implementedCard) {
if (implementedCard != null) {
this.name_ = implementedCard.name_;
/* ... and so on */
}
}
// This deepCopy pattern is required because we use the class of each card to recreate it under certain circumstances
#Override
public Card deepCopy() {
Card copy = null;
try {
try {
copy = this.getClass().getConstructor(ImplementedCardList.ImplementedCard.class).newInstance(this.implementedCard);
} catch(NoSuchMethodException e) {
if(!this.getClass().equals(TestHero.class)) {
log.warn(this.getClass().toString() + " is missing ImplementedCard constructor");
}
copy = getClass().newInstance();
} catch(InvocationTargetException e) {
log.error("InvocationTargetException error", e);
copy = getClass().newInstance();
}
} catch(InstantiationException e) {
log.error("instantiation error", e);
} catch(IllegalAccessException e) {
log.error("illegal access error", e);
}
if (copy == null) {
throw new RuntimeException("unable to instantiate card.");
}
copy.name_ = this.name_;
/* ... and so on */
return copy;
}
}
This base class is then extended like so:
public class Minion extends Card implements CardEndTurnInterface, CardStartTurnInterface {
public Minion() {
super();
}
public Minion(ImplementedCardList.ImplementedCard implementedCard) {
super(implementedCard);
}
#Override
public void initFromImplementedCard(ImplementedCardList.ImplementedCard implementedCard) {
if (implementedCard != null) {
super.initFromImplementedCard(implementedCard);
/* custom init goes here */
}
}
/* other class details follow */
}
public abstract class Hero extends Minion implements MinionSummonedInterface {
public Hero() {
super();
}
public Hero(ImplementedCardList.ImplementedCard implementedCard) {
super(implementedCard);
}
/* no custom init; other class details follow */
}
public class Hunter extends Hero {
public Hunter() {
super();
}
public Hunter(ImplementedCardList.ImplementedCard implementedCard) {
super(implementedCard);
}
/* no custom init; other class details follow */
}
This goes on for hundreds of classes. What I want to do is pull out the constructors that do nothing but call super with the same parameters but when I do, it breaks the getConstructor call in deepCopy.
For each class, you can do:
Hero h = new Hero();
Class hc = h.getClass();
// Get super class and its constructor.
Class<?> sc = hc.getSuperclass();
Constructor scConst = sc.getConstructor(ImplementedCard.class);
// Get super class's parent and its constructor.
Class<?> ssc = sc.getSuperclass();
Constructor sscConst = ssc.getConstructor(ImplementedCard.class);
You could also put this in a loop until you get to Object.class or some other point in the class hierarchy where you'd like to break.
As #nhylated suggested, try
this.getClass().getSuperClass()
Here is a nice explanation regarding why
super.getClass()
behaves like it does.
I'm not sure if I'm asking this right, as I'm attempting to teach myself Java. I have a class which contains my main method, and within this class are several subclasses that need access to my user settings using java.util.Properties. I have to create the properties object in every subclass in order to make it work, and I can't reference the object using configFilePath, it must be null. I'm wondering if I can create this public object within the parent class, so I don't need to create it in all of its subclasses? Here is my code, I'm really not sure I'm doing this right although it works.
public class Frame1 extends JFrame {
Settings config = new Settings(); //this is the object I want to reference within subclasses
class Update extends SwingWorker<Integer, Void> { //first subclass
#Override
protected Integer doInBackground() throws Exception {
Settings config = new Settings(configFilePath); //yet I have to create the object within every subclass, this time an argument is required.
String templateDir = config.getProperty("templatedir");
String writePath = config.getProperty("outputdir");
//do some logic code, not required for my question
}
#Override
protected void done() {
Update2 update2 = new Update2();
update2.execute(); //start the next subclass which also needs access to Settings(configFilePath)
}
}
}
public class Settings extends JFrame {
String configFilePath = "C:/path/to/settings.properties";
Properties properties = new Properties();
public Settings(String configFilePath) throws IOException {
this.configFilePath = configFilePath;
FileInputStream fis = null;
try {
fis = new FileInputStream(configFilePath);
properties.load(fis);
} catch (FileNotFoundException e) {
setDefaults();
} finally {
if (fis != null) {
fis.close();
}
}
}
}
I'm not sure if I'm doing this right or not, it seems to work but seems to be rather redundant having to create the config object every time I need to access my user settings. I hope this hasn't been asked before, and if it has please link me, as I could not find it.
You can create the Setting class as a Singleton pattern, here is one example:
public class Settings extends JFrame{
String configFilePath = "C:/path/to/settings.properties";
Properties properties = new Properties();
private static Settings instance;
public static Settings getInstance(){
if(instance==null){
instance = new Setting();
}
return instance;
}
private Settings() throws IOException {
FileInputStream fis = null;
try {
fis = new FileInputStream(configFilePath);
properties.load(fis);
} catch (FileNotFoundException e) {
setDefaults();
} finally {
if (fis != null) {
fis.close();
}
}
}
}
Usage in any other class of your system:
Settings.getInstance().getProperty("...");
From Update you can use Frame1.this to access the this of Frame1 (because Update is an inner class of Frame1).
Then to access config you can use Frame1.this.config.
Here is a working example:
public class PrefixerFactory {
private String prefix; // Used by Prefixer
public PrefixerFactory(String prefix) {
this.prefix = prefix;
}
public Prefixer createPrefixer() {
return new Prefixer();
}
public class Prefixer { // Inner class
public String addPrefix(String value) {
// Using "prefix" from PrefixerFactory
return PrefixerFactory.this.prefix + value;
}
}
public static void main(String[] args) {
Prefixer helloPrefixer = new PrefixerFactory("Hello ").createPrefixer();
Prefixer goodbyePrefixer = new PrefixerFactory("Good bye ").createPrefixer();
System.out.println(helloPrefixer.addPrefix("world")); // Hello world
System.out.println(goodbyePrefixer.addPrefix("world")); // Good bye world
}
}