Basically, i have a class where i have my arrays in, which is like this
public final class DepotDatabase {
private Driver[] arrayDrivers;
public DepotDatabase() {
arrayDrivers = new Driver[4];
arrayDrivers[0] = new Driver(1234, 1234, 0); // sample driver
arrayDrivers[1] = new Driver(4444, 4444, 0); // sample driver
arrayDrivers[2] = new Driver(1337, 1337, 1); // sample manager
arrayDrivers[3] = new Driver(1234, 1234, 0); // sample driver
}
and i want to print this array in another class, i did set up the array in another class
public Driver(int username, int password, int managerCheck) {
this.username = username;
this.password = password;
this.managerCheck = managerCheck;
}
but now i want to be able to print out all the drivers, but in another class which will be called ViewDrivers or something similar
You can create a method inside DepotDatabase to print the array, then create an object from and call print method.
public final class DepotDatabase {
private Driver[] arrayDrivers;
public void printArray() {
for (int i = 0; i < arrayDrivers.length; i++) {
Driver d = arrayDrivers[i];
System.out.println("Username : " + d.getUsername());
System.out.println("Password : " + d.getPassword());
System.out.println(" Manager Check: " + d.getManagerCheck());
}
}
the from the test class you can do:
public void execute() {
DepotDatabase ddb = new DepotDatabase();
ddb.printArray();
}
That's why you'll need to have getters and setters. You should have:
public Driver[] getDrivers() {
return arrayDrivers;
}
and in the other class, you simply call it (and print it or whatever).
Read this tutorial.
If you plan to print your array in another class you show create an accessor to it.
The common pattern for Java is to use "get plus name off attribute", getDrivers() you should also avoid the class name in such geter as it may changed due to application life.
public final class DepotDatabase {
//your code
public Driver[] getDrivers() {
return this.arrayDrivers;
}
}
Next question to answer is a returning the whole array is good idea. When you return it as above you loose control on it. And every one that call that method will be able to change the content of it.
To prevent this you should use so called Defensive copying
public Driver[] getDrivers() {
return Arrays.copyOf(arrayDrivers, arrayDrivers.length);
}
Then person will get an copy of it an will not harm your class.
The issue with this is that consumer of your class will have to call this method every time to get fresh list of cars.
To solve this issue you may want to user the [collection framework] where instead of array you cold define:
List<Driver> drivers new ArrayList<>();
and provide the drivers as [immutable] list
public Iterable<Driver> getDrivers() {
return java.util.Collections.unmodifiableList(drivers);
}
Iterable is an interface, that allow you to obtain an interator the the list consumer of class wold have possibility to traverse it. IF you wan to allow him to check that list contains some driver you can set the return type as Collection
class Storage {
private String items[] = new String[10];
public String[] getItems() {
return Arrays.copyOf(items, items.length);
}
}
class Store {
Storage storage = new Storage();
private void printStorage() {
String[] items = storage.getItems();
for (String item : items) {
}
}
}
Related
I am trying to brushup java after a long time.
Any help is much appreciated.
For demonstration I have Animal Class that has an array of innerclass of Organs.
public class Animal
{
String nameOfAnimal;
Organs [] vitalOrgans = new Organs[3];
public Animal()
{
}
public String getNameOfAnimal() {
return nameOfAnimal;
}
public void setNameOfAnimal(String nameOfAnimal) {
this.nameOfAnimal = nameOfAnimal;
}
#Override
public String toString() {
return "Animal{" + "nameOfAnimal=" + nameOfAnimal + "}";
}
class Organs{
String nameOfOrgan;
public String getNameOfOrgan() {
return nameOfOrgan;
}
public void setNameOfOrgan(String nameOfOrgan) {
this.nameOfOrgan = nameOfOrgan;
}
#Override
public String toString() {
return "Organs{" + "nameOfOrgan=" + nameOfOrgan + '}';
}
}
}
Now in driver file when I make call there is no syntactical error but I get "Exception in thread "main" java.lang.NoSuchFieldError: vitalOrgans"
Animal mamal = new Animal();
mamal.setNameOfAnimal("Chimp");
mamal.vitalOrgans[0].setNameOfOrgan("Heart");
System.out.println(mamal.vitalOrgans[0].getNameOfOrgan());
What would be the way to make this (or similar idea) to work.
Thanks.
You would need to initialize the vitalOrgrans with new Organs(). Like:
public Animal() {
for (int i = 0; i < vitalOrgans.length; i++) {
vitalOrgans[i] = new Organs();
}
}
Because when you say :
Organs[] vitalOrgans = new Organs[3];
You are creating an array of 3 null Organs. Hence the null pointer exception, when accessing "vitalOrgans[i].".
Taking the relevant bit of code:
public class Animal
{
//...
Organs [] vitalOrgans = new Organs[3];
//...
}
Since your declaration of vitalOrgans was never given an access modifier (i.e. one of private, public, protected) it took on default access, which means only other classes in the same package can see it. Since your other block of code is not in the same package, it cannot see the field.
A minimally viable modification to just make it work would be to set the access to public:
public class Animal
{
//...
public Organs [] vitalOrgans = new Organs[3];
//...
}
While this works, it's not necessarily the best solution, as if you ever change how vitalOrgans is represented, or need to perform any validation, those edits would have to be done throughout the application. Thus, a better solution (and also, a major stylistic convention in Java for those exact reasons) is to make it (and all your fields, in fact) private and access via methods:
public class Animal {
private String nameOfAnimal;
private Organs[] vitalOrgans = new Organs[3];
//...
public Organs[] getVitalOrgans() {
return vitalOrgans;
}
//Alternative accessor that fetches only one organ.
public Organs getVitalOrgan(int index) {
if(index >= 0 && index < vitalOrgans.length)
return vitalOrgans[index];
else
return null;
}
public void setVitalOrgans(Organs[] vitalOrgans) {
this.vitalOrgans = vitalOrgans
}
//...
}
Your caller could then access Organs via either form of the get method (note, you probably want Organs to be public):
Animal.Organs futureMammalHeart = mamal.getVitalOrgan(0); //Animal.Organs due to Organs being an inner class.
if(futureMammalHeart != null) //Demonstration of null check. Safety first!
futureMammalHeart.setNameOfOrgan("Heart");
Animal.Organs[] mammalianVitalOrgans = mamal.getVitalOrgans();
if(mammalianVitalOrgans != null) //Just in case...
System.out.println(mamal.mammalianVitalOrgans[0].getNameOfOrgan());
Also, as Ari mentioned in his answer, don't forget to initialize the organs in your array, otherwise you will get a NullPointerException!
I am using Swagger version 2 with Java Spring. I have declared a property and it works fine and it generates a drop down list of value I assigned.
#ApiParam(value = "Pass any one Shuttle provider ID from the list", allowableValues = "1,2,3,4,10")
private Long hotelId;
Now, I need a way to populate this list which is passed in allowableValues from my database as it could be random list as well as huge data. How can I assign list of values dynamically from database in this allowableValues?
This question is bit old, I too faced the same problem so thought of adding here which may help some one.
//For ApiModelProperty
#ApiModelProperty(required = true, allowableValues = "dynamicEnum(AddressType)")
#JsonProperty("type")
private String type;
Created a component which implements ModelPropertyBuilderPlugin
#Component
#Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1)
public class ApiModelPropertyPropertyBuilderCustom implements ModelPropertyBuilderPlugin {
private final DescriptionResolver descriptions;
#Autowired
public ApiModelPropertyPropertyBuilderCustom(DescriptionResolver descriptions) {
this.descriptions = descriptions;
}
public void apply(ModelPropertyContext context) {
try {
AllowableListValues allowableListValues = (AllowableListValues) FieldUtils.readField(context.getBuilder(),
"allowableValues", true);
if(allowableListValues!=null) {
String allowableValuesString = allowableListValues.getValues().get(0);
if (allowableValuesString.contains("dynamicEnum")) {
String yourOwnStringOrDatabaseTable = allowableValuesString.substring(allowableValuesString.indexOf("(")+1, allowableValuesString.indexOf(")"));
//Logic to Generate dynamic values and create a list out of it and then create AllowableListValues object
context.getBuilder().allowableValues(allowableValues);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean supports(DocumentationType delimiter) {
return SwaggerPluginSupport.pluginDoesApply(delimiter);
}
}
Similary for ApiParam we can create component which will implement ParameterBuilderPlugin
#Override
public void apply(ParameterContext context) {
#SuppressWarnings("Guava") final Optional<ApiParam> apiParam =
context.resolvedMethodParameter().findAnnotation(ApiParam.class);
if (apiParam.isPresent()) {
final String allowableValuesString = apiParam.get().allowableValues();
//Your logic here
context.parameterBuilder().allowableValues(allowableValues);
}
}
You need to create constructor in SwaggerConfiguration class.
#Autowire service and withdraw data you need from database
assign this to final variable
assign this final variable to allowableValues in annotation
enjoy not efficient api
private final String allowableValues;
public SwaggerConfiguration() {
List<YourEntitiy> list = someService.findAll();
//code to get every value you need and add create comma separated String
StringJoiner stringJoiner = new StringJoiner(",");
stringJoiner.add(list.get(0).getValue());
this.allowableValues = stringJoiner.toString();
}
#ApiParam(allowableValues = allowableValues)
But I think it's bad idea getting all ids from database just to create allowable values. Just validate in api method if that id exist and/or Create new api to get ids from database, use pagination from Spring Data project, like PageImpl<> javadocs
I have an arraylist of my custom class and for each of those I would like to each keep their own arraylist of computers. Here is my code for the class:
class Services {
public String name;
public String path;
public ArrayList<String> computers = new ArrayList<>();
public Services(String name, String path, String computer) {
this.name = name;
this.path = path;
this.computers.add(computer);
}
public String getName() {
return name;
}
public String getPath() {
return path;
}
public void addComputer(String computerName) {
this.computers.add(computerName);
}
}
In my main method I am checking my arraylist of Service for an object with the same name and if it exist then I just want to add that to the arraylist for that object.
However, this is not working and it seems I am just ending up with just one arraylist of all computers not specific to each object of Service.
Here is the section of my main method that uses this class.
stream.iterator().forEachRemaining(x -> {
try {
final boolean[] nextLine = {false};
lines(x.toAbsolutePath(), Charset.forName("UTF-16")).forEach(y -> {
if (!nextLine[0]) {
// Finding Separator
if (y.contains("-----------")) {
//Letting the program know the next line is a service.
nextLine[0] = true;
}
} else {
//Splitting the service name from the path.
String[] service = y.split(" + ");
final boolean[] exists = {false};
String computerName = x.getFileName().toString().substring(0, x.getFileName().toString().length() - 4);
allServices.iterator().forEachRemaining(z -> {
if (z.name.contains(service[0])) {
exists[0] = true;
}
});
if (!exists[0]) {
//Creating new service object if it does not exisit.
//Params are Service name, service path, computer name
Services serviceToAdd = new Services(service[0], service[1], computerName);
//Then adding it to the list to be printed out later.
allServices.add(serviceToAdd);
} else {
//Service name already exists, just adding the computer name to its list of affected computers.
allServices.iterator().forEachRemaining(z -> {
if (z.name.contains(service[0])) {
if (!z.computers.contains(computerName)) {
z.addComputer(computerName);
}
}
});
}
}
}
);
} catch (Exception ex) {
}
});
Ultimately, I am trying to compile a list of services. With that list of services I need to know the name of the service, the path, and which computers have them. I am getting the computer name from the name of the file. It appears that the list of computers for each service is the same list instead of a different list for each service. How do I fix this? Do I need to make a list of lists? That seems redundant and ill performing.
It's pretty hard to tell you what you are missing as you do not provide us the main method which is the most important one relating to your post.
So, with the few info I had, here a little algorithm that would loop over all your stored computers according to the code you posted. That should help you figure out what you are missing, else please post the main method.
public static void main(String args[]) {
String newComputer = "UberPC3000x";
boolean alreadyExistSomeWhere = false;
for (int i = 0; !alreadyExistSomeWhere && i < allMyServices.size(); i++) {
for (int j = 0; !alreadyExistSomeWhere && j < allMyServices.get(i).computers.size(); j++) {
alreadyExistSomeWhere = allMyServices.get(i).computers.get(j).equals(newComputer);
}
}
if (!alreadyExistSomeWhere) //Then it means it was not found and you are free to add wherever you want.
{
}
}
I'm trying to create two objects of a Silo class in a SiloManager class, so that I can access both objects' methods. But I can't seem to make the SiloManager constructor work, nor to instance the classes properly. (I'm a beginner in java). Here's my code:
public class GrainSiloManager {
public GrainSilo silo1 = new GrainSilo(100);
public GrainSilo silo2 = new GrainSilo(50);
public GrainSiloManager(GrainSilo silo1, GrainSilo silo2) {
this.silo1 = silo1;
this.silo2 = silo2;
}
private void showStatus() {
System.out.println("The current grain in silo1 is: " + silo1.getGrain());
System.out.println("The current grain in silo2 is: " + silo2.getGrain());
}
}
As I say i'm a beginnger so go easy heh, thanks for any help.
public GrainSilo silo1 = new GrainSilo(100);
public GrainSilo silo2 = new GrainSilo(50);
public GrainSiloManager(GrainSilo silo1, GrainSilo silo2) {
this.silo1 = silo1;
this.silo2 = silo2;
}
This will get compiled as:
public GrainSilo silo1;
public GrainSilo silo2;
public GrainSiloManager(GrainSilo silo1, GrainSilo silo2) {
this.silo1 = new GrainSilo(100);
this.silo2 = new GrainSilo(50);
this.silo1 = silo1;
this.silo2 = silo2;
}
which as you can see makes little to no sense. You're overwriting the object that you make, with the objects passed into the constructor.
Your constructor is going to replace the "public!" silo1 and silo2 objects with whatever is passed in. You could change your constructor like this
public GrainSiloManager() {
super();
}
or the even shorter (but equivalent)
public GrainSiloManager() {
}
And then call it like this
new GrainSiloManager().showStatus();
or you can use your existing approach (which will replace the GrainSoloManager.silo1 and GrainSoloManager.silo2 in your constructor)
GrainSilo silo1 = new GrainSilo(100);
GrainSilo silo2 = new GrainSilo(50);
new GrainSiloManager(silo1, silo2).showStatus();
I have a Register class contains 8 sets& gets methods
using:
public class Register {
public Register(String Username) {
JFrame myFrame = new JFrame();
}
public void setUname() {
JoptionPane.showInputDialog(myFrame, "Enter Username");
}
public String getUname() {
return Uname;
}
}
There are other methods, 8 in total all requiring user input as String or double.
How in another class, can I import the methods into an ArrayList?
public class RegisterApp {
public addUser() {
ArrayList<Register> MyReg = new Arraylist<Register>();
myReg.add(Class Register);
}
}
Uncertain really of what goes after myReg.add
You need to add a reference to a Register.
public class RegisterApp {
public addUser() {
ArrayList<Register> MyReg = new Arraylist<Register>();
//Make an instance of Register and add it to the list
myReg.add(new Register("Me"));
}
}
You also mention adding methods to the list. What do you mean by that? What else are you trying to do? Do you want to call those methods on the instances in the list? You can do that like this:
for (Register reg : myReg) {
System.out.println(reg.getUname());
}
Note:
Your set method doesn't actually save the value anywhere. You are not storing the result in uname (which should be lowecase u). In general, setters are written so they are passed the new value in. This way you are not tied to using an input dialog anytime you change the name. That is a UI decision and should not effect the data model.
public void setUname(String uname) {
this.usname = uname;
}