I have written some Java code with 3 simple classes where the first, Controller, has the main method and creates the instances of the other classes. Floaters is a classes that creates a linked list of Floater instances, each with a particular length and boolean value to say if they are vertical or not. My problem, as it says in the commented lines of the first class, is that both "humans" and "otters" Floaters instances are getting assigned the same values and thus have the same size....
Any suggestions on how to fix this?
Thanks in advance!
public class Controller{
private static Floaters humans;
private static Floaters otters;
public static void main(String[] args)
{
otters = new Floaters();
humans = new Floaters();
otters.addFloater(2, true);
otters.addFloater(3, true);
//this should read "2" and it does
System.out.println(otters.size());
//this should read "0" but reads "2". Why?
//How can I get it to read "0"?
System.out.println(humans.size());
}
}
import java.util.LinkedList;
public class Floaters {
private static LinkedList<Floater> llf;
Floaters()
{
llf = new LinkedList<Floater>();
}
public void addFloater(int length, boolean is_vertical)
{
Floater floater = new Floater(is_vertical, (byte)length);
llf.add(floater);
}
public int size()
{
return llf.size();
}
}
public class Floater {
int length;
boolean is_vertical;
Floater(boolean is_vertical, int length)
{
this.length = length;
this.is_vertical = is_vertical;
}
}
The llf in your Floaters-class is static. When you make variables static, they're linked to the class rather than the instance, and thus both instances of Floaters use the same list.
To correct this, simply remove the static from your declaration of the variable.
in floaters, llf should NOT be static
Because of static:
private static LinkedList<Floater> llf;
In this case static means a class field, shared among all instances of a class.
For example - mathematic functions in Java are declared as static metohods of the class java.lang.Math, matemathematical constants are static atributes of this class. So if you use sin(x), you are using always the same method.
Related
I am trying to use a list of function references as a lookup table (avoiding the need for a long switch statement). The code worked for a list of static methods, but when I tried to use non-static (i.e. instance) methods in the list, Java gives several errors regarding the types not matching.
Here is a minimal example:
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
public class MethodReferences {
// My original list of static references
private final static List<Function<Integer, Integer>> lookupTable = Arrays.asList(MethodReferences::f1, MethodReferences::f2);
// This doesn't work
// private final List<Function<Integer, Integer>> lookupTable = Arrays.asList(MethodReferences::f3, MethodReferences::f4);
private static int f1(int x) { return x * 2; }
private static int f2(int x) { return x * 3; }
private int f3(int x) { return x * 2; }
private int f4(int x) { return x * 3; }
public void run() {
System.out.println(lookupTable.get(1).apply(3));
}
public static void main(String[] args) {
MethodReferences testClass = new MethodReferences();
testClass.run();
}
}
The errors I received were all for the line containing the non-static definition:
Type mismatch: cannot convert from List<Object> to List<Function<Integer,Integer>>
and:
The target type of this expression must be a functional interface
I tried using this:: instead of MethodReferences:: before the function names. The code then compiled, but when it runs, nothing happens, probably because this has to be used within non-static functions.
I then moved the initialisation of the array (still using this:: to within the class constructor, but it continued to produce no output when run.
I've checked through the documentation and tutorials on method references in Java, but I cannot find an examples of creating references to instance methods within the class it is defined in (and I cannot find any examples of lists of function references either).
I'm aware that in the main method, you can do testClass::f1, but for my specific situation (not the example code) I do not even have a main class (the class is instantiated by another library), so this approach isn't possible. The methods have to be non-static because I need to be able to modify instance variables within them.
Edit:
It turns out that using this:: does work for the example code, although I am still unsure as to why it is valid (surely you can only use this within a non-static function?)
You need to use BiFunction instead of Function. The first argument is the implicit this argument.
public class MethodReferences {
private final static List<BiFunction<MethodReferences, Integer, Integer>> lookupTable
= Arrays.asList(MethodReferences::f3, MethodReferences::f4);
private int f3(int x) { return x * 2; }
private int f4(int x) { return x * 3; }
public void run() {
System.out.println(lookupTable.get(1).apply(this, 3));
}
public static void main(String[] args) {
MethodReferences testClass = new MethodReferences();
testClass.run();
}
}
output:
9
For instance method references which use the ClassName::functionName format, instead of instanceName::functionName, you also need to pass the specific instance of the class to the function when calling .apply().
This means that your method references are actually need to be a BiFunction<MethodReferences, Integer, Integer>, even though there is only one explicit parameter to the function.
When calling the method, you also need to pass this into apply:
import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;
public class MethodReferences {
// To refer to non-static methods by class name,
// you must pass in the instance explicitly:
private final List<BiFunction<MethodReferences, Integer, Integer>> lookupTable = Arrays.asList(MethodReferences::f3, MethodReferences::f4);
private int f3(int x) {
return x * 2;
}
private int f4(int x) {
return x * 3;
}
public void run() {
// We need to pass this in, because it isn't implicit
// for ClassName::functionName references:
System.out.println(lookupTable.get(1).apply(3));
}
public static void main(String[] args) {
MethodReferences testClass = new MethodReferences();
testClass.run();
}
}
This question is similar to singleton, but i need to create a class that can allow 'n' number of objects only, Below is my code
public class MSInt {
private static MSInt instance = null;
private static int count = 0;
private MSInt()
{
}
public static MSInt getInstance()
{
if(count < 5){
instance = new MSInt();
count++;
return instance;
}
else
{
return null;
}
}
}
This is working but i am thinking a better solution than this if any.
I think this would be a much cleaner way of doing it. You wouldn't need any counters.
Also it looks nice.
import java.util.ArrayList;
public class MSInt {
private static int MAX_OBJS = 10;
private static ArrayList<MSInt> instances = new ArrayList<MSInt>(MAX_OBJS);
private MSInt() {}
public static MSInt mkInstance() {
if(instances.size() < MAX_OBJS){
MSInt obj = new MSInt();
instances.add(obj);
return obj;
} else {
return null;
}
}
public static ArrayList<MSInt> getInstances() {
return instances;
}
}
Your Code is :
private static MSInt instance = null;
this is overwrite methods;
use like this Array :
private static MSInt[] instance = null;
and use a for loop:
for(int i=0;i<5;i++)
{
instance[i] = new MSInt();
return instance[i];
}
I suggest you to use a decorator pattern
so create a class LimitedList<T> extends AbstractList<T> and override add methods in order to check if size is exceeded
I've put code here (gist)
Few suggestions:
replace public static MSInt getInstance() to public static MSInt getInstance(int number). That way you will be able to specify every time what object you are going to get.
Define difference between instances. What attributes does your instances possess? In your example all objects looks the same - it becomes unclear why do you need more than one of them.
Think about initialization. Do you need lazy initialization, or can you initialize all the instances in class initialization. Then you can declare them public static final and deny defining getInstance()
BTW, enum is class that has exactly n instances (by design). It's very likely that defining MSInt as enum will be the most convenient for you.
Using an array or collection means that garbage collection won't remove any of your instances without your knowledge, and it means you can retrieve instances later if required. Using an an MSInt[] might be most practical because it is already capable of making sure only a certain number of objects exist in it. The getInstance() method then loops through the array and if it finds an empty slot, creates a new instances, puts it in the empty spot and returns the result.
public class MSInt {
private static MSInt[] instances = new MSInt[10];
private MSInt(){ }
public synchronized static MSInt getInstance() /*throws TooManyException*/{
for(int i = 0 ; i<instances.length() ; i++){
if(instances[i]==null){
MSInt ms = new MSInt();
instances[i] = ms;
return ms;
}
}
// throw new TooManyException("There are already 10 instances of MSInt");
return null;
}
}
Some exception handling might also be useful. You could throw a custom exception to show that too many instances already exist. Which would make it much more manageable later because you can then define more robust custom behavior for if the array is already full. By removing the comments in the class above and creating the below class, that should work nicely.
public class TooManyException extends Exception {
public TooManyException(String message){
super(message);
}
}
Hope this helps.
For example I have a MovieDatabase class that contains a list of Movie objects. In my main code, I initialize all the objects in the MovieDatabase. However I wish to call this MovieDatabase in another class to access the library. How would I do this?
Do I add in get methods in my main code and return it? Or is there another way (eg. changing the list of objects to protected/public?)
Thanks!
Code's supposed to be 3 seperate classes, Main, MovieDatabase & Movie.
An instance of movieDatabase is initialized in Main. Upon construction, it calls loadMovieList() and populates the list from a text file. However I wish to call the same instantiation of movieDatabase from another class in order to access the movies, so that I do not have to repeat the loading.
public class Main {
public static void main(String[] args) {
MovieDatabase movieDatabase = new MovieDatabase();
}
public class MovieDatabase {
ArrayList<Movie>movieList = new ArrayList<Movie>();
String fileAddress = "D:/Users/Mine/School/Java/CZ2002_Assignment/src/MovieDatabase/movieDatabase.txt";
public MovieDatabase()
{
numOfMovie=0;
loadMovieList();
}
public int getNumOfMovie() {
return numOfMovie;
}
public void addMovieToList(Movie movie) {
movieList.add(movie);
numOfMovie++;
}
public Movie selMovieByID(int movieID) {
int index=-1;
for (Movie m : movieList) {
index++;
if (m.getMovieID() == movieID)
break;
}
return selMovieByIndex(index);
}
public Movie selMovieByIndex(int index) {
return movieList.get(index);
}
public void loadMovieList()
{
//loads through text file
addMovieToList(new Movie(tempMovie));
System.out.println("Movie Database loaded");
}
public class Movie{
private int movieID;
private String movieName;
private int movieDuration; //in minutes;
private String movieRating; //G; PG; PG13; NC16; M18; R21;
private boolean has3D;
private boolean status;
}
If you have a class that depends on a NameLibrary, you should inject it via the constructor or a set method.
Firstly, its difficult to assess what issues you truly have without any code to show us.
However you mention main method, as in
public static void main(String args[]){};
this main method is designed specifically to run the application, your compiler needs that specific method, it is not designed to be used as an accessor method
e.g.
public int getValue(){
return value;}
this is not the only reason you can't access the main method variable. main doesn't have a return type (due to the use of void) plus the idea of SCOPE (each method has a scope, any method that contains a variable can see that variable, but nothing outside of it can directly see it without a return type) you use scope to limit what can be accessed or what cannot be accessed outside of the methods or classes (thats why class variables usually will have private, in order to limit accessibility)
Create a getter-method which returns the list inside your NameLibrary. if your other class extends from NameLibrary you can call this getter-method with the object reference to your NameLibrary class.
If you want int x to be accessible from other classes, you write:
public class myClass{
public int x = 0;
}
To access it from other classes, you simply write:
myClass.x ... (do something)
I've got this int variable inside the class StringSplit whose value I need to pass to another class called EndStatement to print out; can't really pass it as a parameter though I think. How can I best get the variable to where I need it? Can someone help with a hint? I've read the Java tutorials but don't quite get them. Variables and passing them around seem to be one of my Achilles' heels in Java programming.
EDIT TO ADD: parseCommands can call several different Statement classes e.g. EndStatement or PrintlnStatement depending on the first element of an Array parsed from a String which serves as a keyword to a HashMap called commandHash. The Statement classes implement the Directive interface which only has a method called execute with the parameterString[] parts. (EndStatement implements Directive). Expanded the parseCommands method to show what's going on.
public class StringSplit
{
public void parseCommands(String fileName)
{
//FileReader and BufferedReader to read a file with the code
//to execute line by line into an ArrayList myString
int lineCounter=0; //need to get this variable's value into class EndStatement
for (String listString: myString)
{
lineCounter++;
String[] parts=listString.trim.split("[\\s]+", 2)//split String into 2 parts
//to get commands
Directive directive= commandHash.get(parts[0])//parts[0] is the hashmap keyword
}
public class EndStatement implements Directive
{
public void execute(String[] parts)
{
//need to get lineCounter here--how?
System.out.print(lineCounter +"lines processed.");
}
public static void main (String[]args)
StringSplit ss = new StringSplit();
ss.parseCommands(args[0]);
}
This is my first time answering a question but I think I'm right.
In StringSplit you want to declare linceCounter in a data field.
public class StringSplit
{
public void parseCommands(String fileName)
{
lineCounter=0; //this is the variable I need to pass into a different class
for (String listString: myString)
{
lineCounter++;
//more code here
}
}
public int getLineCounter()
{
return lineCounter;
}
private int lineCounter; //this is what I call a data field, you should declare these as private as oppose to public to comply with encapsulation
}
Then in your main method call getLinceCounter, then pass what it returns to EndStatment.
Does this make sense? Did I understand your question right?
public class StringSplit
{
private int lineCounter=0;
public void parseCommands(String fileName)
{
for (String listString: myString)
{
lineCounter++;
//more code here
}
}
public int getLineCounter() {
return lineCounter;
}
}
public class EndStatement implements Directive
{
StringSplit ss = new StringSplit();
public void execute(String[] parts)
{
//need to get lineCounter here--how?
System.out.print(ss.getLineCounter() +"lines processed.");
}
public static void main (String[]args)
{
ss.parseCommands(args[0]);
}
}
I think you mix some terms. There is no such thing as passing variables from one class to another. I assume that what you want to do is simply be able to access (set/get) your variable outside StringSplit class. In order to do that you must declare lineCounter outside parseCommands method as StringSplit's property. Currently lineCounter is local to parseCommands method and as such cannot be visible/accessed outside that method not mentioning to be able to access it from outside a class/object. Do that:
public class StringSplit
{
public int lineCounter = 0;
...
Now you'll be able to access lineCounter from different methods of the same class and from methods outside your class. Making lineCounter public gives others full access to it. As 'Jon' has pointed out it may be dangerous sometimes but for this example case is acceptable. You may see how writing from outside can be prevented using 'Nurlan's' private field with member used to provide read acces only.
Right now I have two .java files.
The Main.java:
public class Main {
static int integer = 15;
NeedInteger need = new NeedInteger();
}
and the NeedInteger.java
public class NeedInteger {
System.out.println(integer);
}
This is of course very simplified, but is there any way I can accomplish this?
As many have answered, the correct method is to pass the value in to the constructor of the new class.
If for some reason you cannot do that, then you can use a public static accessor method in Main to access the value (this would be slightly better than just making the field public).
E.g.
public class Main
{
private static int integer = 15;
public static int getInteger()
{
return integer;
}
}
public class NeedInteger
{
public NeedInteger()
{
int integer = Main.getInteger();
}
}
Add a constructor to NeedInteger (and optionally a member if you need to also store it):
public class NeedInteger {
private int integer;
public NeedInteger(int integer) {
this.integer = integer;
System.out.println(integer);
}
}
Then pass your value when you create the instance:
public class Main {
static int integer = 15;
NeedInteger need = new NeedInteger(integer);
}
You would have to do some bad juju moves (like using a global variable) or pass it to the constructor.
NOTE: your
public class NeedInteger {
System.out.println(integer);
}
has no method in it. I would recommend all this to be rewritten as such:
public Class NeedInteger {
NeedInteger(int integer) {
System.out.println(integer);
}
}
If you really want the work to be done on construction.
EDIT: From your comment above.
Instead, have the class structured so:
public Class NeedStringArray {
NeedStringArray(String[][][] stringArr) {
//work with String array here
}
}
That has no real additional overhead, since the actual array will not be passed, but only a reference to it. You WILL likely want to set the array to be final or something, to avoid it being edited in the NeedStringArray constructors.
integer is private, so it cannot be accessed by NeedInteger. you'll have to make it public or use a setter or getter and you'll need to use Main.integer since it's static.
Generally, you set in the Constructor.
Pass in the variable to the class constructor.
An array reference would be just that--a reference.
Or you could pass in the class itself, or use a static (meh).
Per your comment I'd say you can either host your array in a singleton
or as others suggested have the second class accept the reference to the array in the constructor. You can then use Dependency Injection framework (e.g. Guice) to get wire them up