Accessing a private variable from another class - java

NOTE: I have looked at the other posts, but I'm still quite lost.
This is the code for a private variable that I have in one class:
private int readFile( String fileName)
{
try
{
File f = new File( fileName );
Scanner input = new Scanner( f );
while( input.hasNextLine( ) )
{
String s = input.nextLine( );
String[ ] sArr = s.split( " " );
String animal = sArr[ 0 ];
double cost = Double.parseDouble(sArr [ 1 ] );
boolean penNeeded = Boolean.parseBoolean( sArr[ 2 ] );
boolean available = Boolean.parseBoolean( sArr[ 3 ] );
Pet p = new Pet( animal, cost, penNeeded, available );
if (count < animalList.length )
{
animalList[count] = p;
count++;
}
}
input.close( );
}
catch( Exception e )
{
System.out.println("Error reading the file:");
System.out.println( e );
e.printStackTrace( );
}
return count;
}
I need to access it in this piece of code located in another class:
static public void processTransaction( String fileName, PettingZoo pz )
{
try
{
// variable should be accessed here
}
catch( Exception e )
{
System.out.println("Error reading the file:");
System.out.println( e );
e.printStackTrace( );
}
}
How can I do this? I think that I need to use a modifier of some sort, but I don't know how which one or how to implement it.

You cannot directly access private variables from another class. That's the whole point of declaring it private. What you need to do is use setter and getter methods in class A, then call the get method from class B.

If you want access to a private variable, you can use getter and setter methods.
Example:
private int variable = 5; //<--- your private variable of class A
// a public method (into the same class A)
// that allows the sharing of your private variable
public int getVariable() {
return variable;
}
Now you can call the method getVariable() from an other class (B) and take the value of the private variable (of class A).

As per your comment you can access the private int readFile(String fileName) method by changing the modified of the method. Change the modifier of the method to public or protected. Also since the accessing method is static you need to change the method as static.
So change it as
public static int readFile( String fileName)
{
}
In the processTransaction method invoke it as,
ClassName.readFile("file_name.extn");

Related

Using links to static and non-static methods with interface

Why I can call non-static method length() from class String, but I can't call non-static method lengthHelper( String line ) from my class ExpressionHelper?
public static void main(String[] args) {
String[] lines1 = {"H", "HH", "HHH"};
System.out.println(sum(lines1, String::length));
System.out.println(sum(lines1, s -> s.length()));
System.out.println(sum(lines1, ExpressionHelper::lengthHelper)); //wrong
}
interface Expression {
int length(String line);
}
static class ExpressionHelper {
int lengthHelper(String line) {
return line.length();
}
}
private static int sum(String[] lines, Expression func) {
int result = 0;
for (String i : lines) {
result += func.length(i);
}
return result;
}
String::length is an instance method of String. It requires an instance of String to run, which you are providing, because you are passing elements of lines1 to it.
ExpressionHelper::lengthHelper is an instance method of ExpressionHelper. In addition to the explicit String line argument, it requires an instance of ExpressionHelper to run, which you are not providing.
If you made lengthHelper a static method in ExpressionHelper, then you would be able to call it without an instance of ExpressionHelper.
In addition to the answer from khelwood:
If you change your code like this:
public static void main( String[] args )
{
final var expressionHelper = new ExpressionHelper();
String[] lines1 = {"H", "HH", "HHH"};
System.out.println(sum( lines1, String::length ) );
System.out.println(sum( lines1, s -> s.length() ) );
System.out.println(sum( lines1, ExpressionHelper::lengthHelper) ); //wrong
System.out.println(sum( lines1, expressionHelper::lengthHelper) );
}
it works also with ExpressionHelper::lengthHelper (although I should write better ExpressionHelper.lengthHelper() or ExpressionHelper#lengthHelper to avoid further confusion …)
Yes, I know, in this context it is nasty to name the variable same as the class, only having the first letter as lower case: it does not support readability.
But now expressionHelper is that instance of ExpressionHelper that #khelwood mentioned as missing in their answer.

What are the different ways of accessing an ArrayList from a method?

I'm working on some homework programs and I'm required to do stuff in Java using functional programming principles as much as possible. These are the important bits of a program that receives a list of numbers and prints the even ones:
public static void main( String args[ ] )
{
ArrayList<Double> listEven = new ArrayList<Double>();
inputRecursion( );
outputRecursion( );
}
public static void inputRecursion( )
{
Scanner in = new Scanner( System.in );
if( in.hasNextDouble() )
{
if( (in.nextDouble() % 2) == 0 )
{
listEven.add( in.nextDouble() );
}
inputRecursion( );
}
}
public static void outputRecursion( )
{
Iterator<Double> it = listEven.iterator();
if( it.hasNext() )
{
System.out.println( it.next() );
outputRecursion( );
}
}
It's a work in progress, but I haven't got to run it and check the logic because I still have two compilation errors in the lines:
listEven.add( in.nextDouble() );
Iterator<Double> it = listEven.iterator();
These two lines throw "cannot find symbol", and I know this is because the ArrayList was declared in a way that makes in inaccessible from methods outside main. I have a rough understanding of the ways of fixing this. I know about setters and getters and they look simple enough from what I researched, but I consider those the last resource since I'm trying to avoid the use of variables (I am aware that my program has other mutable stuff; I'm working on it) in order to meet the restrictions of the exercise as much a possible. I also know that I can make it public static, but then that causes like 15 more errors to appear, and from what I looked up it requires to be "initialized" and it also involves variables.
Are there any other ways to make the ArrayList accessible from those two methods? I'm specially interested in ways that don't involve variables or iteration.
Declare the ArrayList as static but outside of the main function like below:
static ArrayList<Double> listEven = new ArrayList<Double>();
public static void main( String args[ ] )
{
inputRecursion( );
outputRecursion( );
}
public static void inputRecursion( )
{
Scanner in = new Scanner( System.in );
if( in.hasNextDouble() )
{
if( (in.nextDouble() % 2) == 0 )
{
listEven.add( in.nextDouble() );
}
inputRecursion( );
}
}
public static void outputRecursion( )
{
Iterator<Double> it = listEven.iterator();
if( it.hasNext() )
{
System.out.println( it.next() );
outputRecursion( );
}
}

Best practice for adding elements to an ArrayList during object construction?

So I'm working on a project for my online AP Computer Science class and have run into a problem... Here's the original class definition I was given to build upon (stripped of code irrelevant to my question):
Note: The constructor of the Bin class accepts a single argument, a String. The String is representative of the Bin's name.
import java.util.*;
public class Warehouse
{
// Declare instance variables here
public Warehouse( int binMax )
{
myBinMax = binMax;
myCatalog = new ArrayList<MusicMedia>();
myBins = new ArrayList<Bin>( 5 );
// Code that will start the warehouse
// off with 5 empty bins
}
public void addBin()
{
myBins.add( new Bin( "B" + myBins.size() ) );
}
}
My job is to replace the areas commented out with actual code implementation. While the declaration of the instance variables is very straight forward, I'm rather torn on the best way to implement the code mentioned in the second comment.
In short, which is the best way to complete the above constructor?
Solution A:
private int myBinMax;
private ArrayList<MusicMedia> myCatalog;
private ArrayList<Bin> myBins;
public Warehouse( int binMax )
{
myBinMax = binMax;
myCatalog = new ArrayList<MusicMedia>();
myBins = new ArrayList<Bin>( 5 );
for(int i = 0; i < 5; i++)
{
myBins.add( new Bin( "B" + myBins.size() ) );
}
}
Solution B:
private int myBinMax;
private ArrayList<MusicMedia> myCatalog;
private ArrayList<Bin> myBins;
public Warehouse( int binMax )
{
myBinMax = binMax;
myCatalog = new ArrayList<MusicMedia>();
myBins = new ArrayList<Bin>( 5 );
for(int i = 0; i < 5; i++)
{
addBin(); // <= Is this considered bad practice?
}
}
Solution C:
// Some magical wizard code I would have never thought of. XD
Thanks in advance!
Can you use Java 8?
final List<Bin> bins = IntStream.range(0, 5).
mapToObj(i -> new Bin("Bin" + i)).
collect(Collectors.toCollection(ArrayList::new));
Otherwise, both your solutions looks fine. I would prefer B as you already have an addBin method with one caveat. You must make addBin final as it is a public method. You should only call private or final methods from constructors otherwise you risk someone (possibly you) overriding that method in a subclass and then the subclasses method will be called from the superclass constructor before the subclass is initialized.
try to use a constant than magic numbers in code :)
import java.util.*;
public class Warehouse
{
// Declare instance variables here
private static final int INITIAL_BINS = 5;
private static final String DEFAULT_BINNAME = "DefaultBin_";
public Warehouse( int binMax )
{
myBinMax = binMax;
myCatalog = new ArrayList<MusicMedia>();
myBins = new ArrayList<Bin>( INITIAL_BINS );
for(int i = 0; i < INITIAL_BINS; i++)
{
myBins.add( new Bin( DEFAULT_BINNAME + i ) );
//addBin();// This is fine too depends on how flexible you want naming to be:)
}
}
public void addBin()
{
myBins.add( new Bin( "B" + myBins.size() ) );
}
}
While I agree with most everything that's already been said, the java 8 functional programming style one-liner is pretty sexy. Magic numbers / strings should be avoided. If your class hasn't gone over functional style why not move the entire for loop into its own function? Generally the only thing that a constructor should do is initialize the state of your object. To make that explicit I try to keep to one line per member variable and that one line is nothing more than an initialization statement. IMO methods (which can reference the current state of the object) shouldn't be called from a constructor because your object hasn't been created yet. If you want to add functions to help you initialize your object, feel free to do so but keep them static so that the intent of the function (not referring to the state of the object) is clear.
...
private static final int INITIAL_BIN_COUNT = 5;
private static final String BIN_PREFIX = "B";
private final List<Bin> myBins;
public Warehouse(...) {
....
myBins = initMyBins();
}
private static List<Bin> initMyBins() {
final List<Bin> result = new ArrayList<Bin>(INITIAL_BIN_COUNT);
for(int i = 0; i < INITIAL_BIN_COUNT; i++) {
result.add(new Bin(BIN_PREFIX+i));
}
return result;
}
...
P.S. A few other notes, it's generally good practice to code to interface types rather than concrete class types (maybe you haven't covered interfaces yet, but that's what I did changing ArrayList to List.

package rjava jcall error in R

I want to use R to input a parameter into Java, for example "1000". Then method of StringToNum process and output its return to R,namely 1000. Seems it is the work of .jcall(), but I dont know how to do with its parameters.As I dont know Java, Could you please help me?
Thank you very much!
Java code
package com.mingdong.rcalljava.test;
import java.io.PrintStream;
public class StringToNum
{
private String inputString = null;
public StringToNum(String inputString)
{
this.inputString = inputString;
}
public StringToNum()
{
}
public int convertStringToInt()
{
if (this.inputString == null) {
this.inputString = "100";
}
return Integer.valueOf(this.inputString).intValue();
}
public static void main(String[] args)
{
StringToNum stringToNum = new StringToNum();
int num = stringToNum.convertStringToInt();
System.out.println("num:" + num);
}
}
R code
library(rJava)
.jinit()
.jinit('D:/Eclipse/dailyjob/javaProject/TestRCallJava.jar')
## .jaddClassPath("D:\\Eclipse\\dailyjob\\javaProject\\TestRCallJava.jar")
inputString <- .jnew("java.lang.String","1000")
inputString %instanceof% "java.lang.String"
StringToNum <- .jnew("com.mingdong.rcalljava.test.StringToNum")
StringToNum %instanceof% "com.mingdong.rcalljava.test.StringToNum"
.jcall(StringToNum,returnSig= "V", "main",inputString )
Error in .jcall(StringToNum, returnSig = "V", "main") :
method main with signature ()V not found
There are two issues. On the Java side in main you call the constructor new StringToNum() which does not exist. The main method should rather look like:
public static void main( String[] args ) {
StringToNum stringToNum = new StringToNum( args[0] );
int num = stringToNum.convertStringToInt();
System.out.println("num:" + num);
}
Maybe this solves already your problem. However, in general you call static methods in Java not on the object but on the class. If you'd call the main method from Java you'd have to call
StringToNum.main( "1000" );
instead of calling
StringToNum obj = new StringToNum( "" );
obj.main( "1000" );
You should also avoid to call the low-level functions (indicated by starting with a .) of the rJava package. So as indicated in rJava .jcall return type issue the proper call would be
J("com.mingdong.rcalljava.test.StringToNum")$main( "1000" ) # untested

Using switch in Enum

What if I'll use switch in getByIntValue()? Is it really neccessary to use a SparseArray?
public enum Gender {
Unknown(0),
Male(1),
Female(2);
private static final SparseArray<Gender> lookupTable = new SparseArray<Gender>();
static {
for (final Gender gender : EnumSet.allOf(Gender.class)) {
lookupTable.put(gender.intValue, gender);
}
}
private final int intValue;
public static Gender getByIntValue(int val) {
return lookupTable.get(val);
}
private Gender(int intValue) {
this.intValue = intValue;
}
public int getIntValue() {
return intValue;
}
}
Since your int values go from 0 to 2, without hole, you could indeed simply use an array. A switch would also be fine, although it would probably be slightly slower than an array lookup. But unless you call the method billions of times, it won't make any noticeable difference. Use what you find the clearest and easiest to understand and maintain.
If you have posted realistic int values, then you don't need to set them explicitly on each enum member, and don't need switch. Just use
Gender.values()[intValue]
List.copyOf( EnumSet.allOf( Gender.class ) )
Caveat: This exercise in optimization seems silly for all but the most extreme scenario, as mentioned by JB Nizet. For real work, I would probably recommend the solution seen in the Answer by Marko Topolnik. But, for fun, I swung a bat at this ball.
Seems the goal is to render a static unmodifiable collection with very fast access by the given numbers 0, 1, 2.
As of Java 10, we have these new implemented (“default”) methods on the List interface: List.of & List.copyOf. These produce an unmodifiable collection. Though the backing implementation is undocumented and subject to change, I will assume it is something akin to an array with similar performance. Performance might even be faster than a conventional array, if the backing implementation detected the presence of an EnumSet and used some kind of bit vector.
I populate the List by passing an EnumSet to List.copyOf( Collection ).
So, this:
private static final SparseArray<Gender> lookupTable = new SparseArray<Gender>();
static {
for (final Gender gender : EnumSet.allOf(Gender.class)) {
lookupTable.put(gender.intValue, gender);
}
}
…becomes this:
private static final List < Gender > lookupTable = List.copyOf( EnumSet.allOf( Gender.class ) );
Entire class, with main for demo.
package com.basilbourque.example;
import java.util.EnumSet;
import java.util.List;
public enum Gender {
UNKNOWN( 0 ),
MALE( 1 ),
FEMALE( 2 );
private static final List < Gender > lookupTable = List.copyOf( EnumSet.allOf( Gender.class ) );
private final int intValue;
public static Gender getByIntValue ( int val ) {
return lookupTable.get( val );
}
public int getIntValue () {
return intValue;
}
// Constructor
private Gender ( int intValue ) {
this.intValue = intValue;
}
public static void main ( String[] args ) {
// Testing.
System.out.println( Gender.UNKNOWN.intValue );
System.out.println( Gender.getByIntValue( 0 ) );
System.out.println( "----" );
System.out.println( Gender.MALE.intValue );
System.out.println( Gender.getByIntValue( 1 ) );
System.out.println( "----" );
System.out.println( Gender.FEMALE.intValue );
System.out.println( Gender.getByIntValue( 2 ) );
}
}
When run.
0
UNKNOWN
1
MALE
2
FEMALE
By the way, as the biological default, FEMALE should come before MALE.

Categories