non-static variable error when creating own class - java

I often struggle with non-static variable errors. Not sure I have understood the purpose properly when to use static and not. I have the below code where I'm trying to parse a csv file with three columns (date, time, temperature) in to a class I have defined myself.
This bit gives me a non-static variable error.
TempData objt = new TempData();
If anyone knows what I'm doing wrong I'd be very grateful. I've tried google but can't find anything relevant.
package com.company;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
import java.text.SimpleDateFormat;
import java.sql.Timestamp;
public class Main {
public static void main(String[] args) {
Date tempDate;
Date tempTime;
Double tempTemperature;
ArrayList<TempData> data = new ArrayList<TempData>();
TempData objt = new TempData();
//Get scanner instance
Scanner scanner = new Scanner(new File("smhi-opendata.csv"));
//Set the delimiter used in file
scanner.useDelimiter(";");
//Get all tokens and store them in some data structure
while (scanner.hasNext())
{
tempDate = new SimpleDateFormat("dd/MM/yyyy").parse(scanner.next());
tempTime = new SimpleDateFormat("hh:mm:ss").parse(scanner.next());
tempTemperature = Double.parseDouble(scanner.next());
objt.Data(tempDate, tempTime, tempTemperature);
data.add(objt);
}
//Do not forget to close the scanner
scanner.close();
}
public class TempData{
private Date date;
private Date time;
private double temperature;
public void Data (Date d, Date t, double te){
date = d;
time = t;
temperature = te;
}
}
}

First off the Data function just updates the values rather than create a new TempData object. Secondly the main function can't use the TempData class where it is currently.
I'd go for something like this instead:
public class TempData {
private Date date;
private Date time;
private double temperature;
public TempData(Date date, Date time, double temperature) {
this.date = date;
this.time = time;
this.temperature = temperature;
}
public static void main(String[] args) throws Exception {
Date tempDate;
Date tempTime;
Double tempTemperature;
ArrayList<TempData> data = new ArrayList<TempData>();
// Get scanner instance
Scanner scanner = new Scanner(new File("smhi-opendata.csv"));
// Set the delimiter used in file
scanner.useDelimiter(";");
// Get all tokens and store them in some data structure
while (scanner.hasNext()) {
tempDate = new SimpleDateFormat("dd/MM/yyyy").parse(scanner.next());
tempTime = new SimpleDateFormat("hh:mm:ss").parse(scanner.next());
tempTemperature = Double.parseDouble(scanner.next());
TempData objt = new TempData(tempDate, tempTime, tempTemperature);
data.add(objt);
}
// Do not forget to close the scanner
scanner.close();
}
}

The problem is that you are accessing a non static class from a static context. The main method (public static void main() {}) has the keyword static so it is in the class (static) context. Your inner class TempData is not static, so it belongs to the instance (non static) context.
You can access the class context from instance context, but not vice versa. So you have tow options:
Move your TempData class to the static context:
public class Main {
public static void main(String[] args) {
// ...
TempData objt = new TempData();
// ...
}
public static class TempData{
// ...
}
}
Or access your TempData from non static context. For example:
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
// ...
TempData objt = new TempData();
// ...
}
public class TempData {
// ...
}
}
To read more about this you can follow this official explanation.

Related

How can I use a user input String from one method in another?

This point of this program is to limit the character length of a username to 20 characters. It is one part of a larger program which currently only contains a Main method. In the interest of cleaning and clarifying my code, I would like to separate the various functions into distinct methods.
Currently, I'm trying to set class variables so that they can be used in multiple methods. This is what I have so far:
public class Program
{
Scanner read = new Scanner(System.in);
String firstName = read.nextLine();
String lastName = read.nextLine();
public void main(String[] args) {
domainCharLimit();
}
public void domainCharLimit() {
String firstNameNew = firstName.replace("'", "");
String lastNameNew = lastName.replace("'", "");
String domainUsername = firstNameNew + "." + lastNameNew;
if (domainUsername.length()>20) {
String cutName = domainUsername.substring(0, 20);
domainUsername = cutName;
}
System.out.print(domainUsername);
}
}
I have tried setting one or both methods to static, which did not resolve the issue. In this state, when run, the program will not return an errors but rather give "no output"
Main method has to be static! It is entry to your program and its signature has to be like that.
In order to call non static method inside it you need to instantiate an object and call it on that object. In your case something like
public static void main(String[] args) {
Program p = new Program();
p.domainCharLimit();
}
First: Main Method should be always static.
Second: Because you are calling domainChatLimit() from Main(static) than it should be also static
Third: Because you used firstName, lastName attributes in a static method domainChatLimit() then they should be also static
Fourth: Scanner should be also static because you are using it to get firstName, lastName and they are both static.
NOTE: There is no need to define a new instance of this class to call an internal method
Solution should be like below (tested successfully):
import java.util.Scanner;
public class Program{
// variables below should be defined as static because they are used in static method
static Scanner read = new Scanner(System.in);
static String firstName = read.nextLine();
static String lastName = read.nextLine();
// Main method is static
public static void main(String[] args) {
//There is no need to define a new instance of this class to call an internal method
domainCharLimit();
}
// calling from main static method so it should be static
public static void domainCharLimit() {
String firstNameNew = firstName.replace("'", "");
String lastNameNew = lastName.replace("'", "");
String domainUsername = firstNameNew + "." + lastNameNew;
if (domainUsername.length()>20) {
String cutName = domainUsername.substring(0, 20);
domainUsername = cutName;
}
System.out.print(domainUsername);
}
}
if you want to create a Generic Util for that functionality you can do below logic:
PogramUtil.java
import java.util.Scanner;
public class ProgramUtil {
Scanner read = new Scanner(System.in);
String firstName = read.nextLine();
String lastName = read.nextLine();
public void domainCharLimit() {
String firstNameNew = firstName.replace("'", "");
String lastNameNew = lastName.replace("'", "");
String domainUsername = firstNameNew + "." + lastNameNew;
if (domainUsername.length()>20) {
String cutName = domainUsername.substring(0, 20);
domainUsername = cutName;
}
System.out.print(domainUsername);
}
}
now you can call this way :
Program.java
public class Program{
// Main method is static
public static void main(String[] args) {
ProgramUtil programUtil = new ProgramUtil();
programUtil.domainCharLimit();
}
}

Using scanner input in getters and setters?

I have two java classes, while one contains the getters and setters the other is a driver class. I need the user input from the scanner in the driver class to be in one of the getters in the first class. The user input has to be a double because it will be used as a formula in the getter.
//First Class
public class shopping
{
String orangeSelected;
public double getOrangeSelected()
{
return (user input makes a formula to be returned to the driver class)
}
public void setOrangeSelected(String orangeSelected)
{
this.orangeSelected = orangeSelected;
}
}
//Driver Class
import java.util.Scanner
public class shoppingApp
{
public static void main(String[] args)
{
Scanner inputOrangeSelected = new Scanner(System.in)
System.out.println("Premium Oranges");
String orangeSelected = inputOrangeSelected.nextLine();
}
}
The problem you are facing is that you are not storing the String "orangeSelected" into an instance of your shopping object. In order to do that, you would would to create an instance of your shopping object, and then call the "setOrangeSelected" method.
Example
Here is how it would look in your driver class:
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
/* I would recommend changing your shopping class name to Shopping
for correct naming conventions.*/
Shopping shopping = new Shopping();
/* Changed the system out to a question. Not a nessicary change.
All depends on what your program is doing. */
System.out.println("What type of oranges would you like?");
String orangeType = input.nextLine();
// Here you are actually storing the user input into the shopping object.
shopping.setOrangeSelected(orangeType);
}
Once the input is placed in an object, you can take that variable, and call "getOrangeSelected" on it to return the type of orange, like so:
System.out.println(shopping.getOrangeSelected());
Extra Resources
I suggest you look at the Oracle naming conventions for the java language. It is helpful to follow them to improve readability of your code.
Edit
For clarity, I also wanted to add that you have the getter method return the orangeSelected variable, like so:
public double getOrangeSelected() {
return orangeSelected;
}
What would really be best is to put everything in one class, there is no reason to separate 1 class into 2 just to keep getters and setters separate from the rest, it makes no sense. I do wonder if you have misunderstood your assignment.
import java.util.Scanner;
class shoppingApp
{
//since it's an instance field not local to the class it's declared here instead of main
static String orangeSelected = "";
public static void main(String[] args)
{
//orange selected is an odd name for a scanner, just use scan or something similar
Scanner scan = new Scanner(System.in); //note that you were missing a semicolon
System.out.println("Premium Oranges\n"); //include a new line or a space before asking for input, for example with \n
orangeSelected = scan.nextLine();
}
//setter
public static void setOrangeSelected(String str)
{
orangeSelected = str;
}
//getter
public static String getOrangeSelected()
{
return orangeSelected;
}
//Note that all methods and instance fields are static because the main method must be static if you don't understand this yet that's ok.
}
Now if for some reason you absolutely had to use two classes it would look something like this, although I'd note that just copying and pasting my code without understanding it would be cheating.
import java.util.Scanner;
class shoppingApp
{
//normally this shouldn't be public
public static String orangeSelected = "";
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
System.out.println("Premium Oranges\n");
orangeSelected = scan.nextLine();
}
}
class gettersAndSetters
{
//setter
public void setOrangeSelected(String str)
{
Main.orangeSelected = str;
}
//getter
public String getOrangeSelected()
{
return Main.orangeSelected;
}
}

How would I input data into an array from user? I'm using accessors and mutators

Okay. Here's my first page with the accessors and mutators
public class TimeCard {
private int employeeNum;
private String[] clockInTimes = new String[14];
private String[] clockOutTimes = new String[14];
private float[] decimalClockIn = new float[14];
private float[] decimalClockOut = new float[14];
private float[] timeElapsed = new float[14];
public String[] getClockInTimes()
{
return clockInTimes;
}
public void setClockInTimes(String[] value)
{
clockInTimes = value;
}
}
My second class acessessing those set/get arrays.
How would I ask for user input for each array subscript 0-13?
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
TimeCard josue = new TimeCard();
System.out.println("Enter Monday Clock In Times:");
//not sure if this is right?
josue.setClockInTimes[0](reader.next());
}
}
By the way I need to do it like this because teacher wants it this way. I'm just not really sure how to get user input and put it into an array using an object class.
I'd probably start by changing your setter to take an index and a value, so something like this:
public void setClockInTime(int day, String clockInTime) {
this.clockInTimes[day] = clockInTime; // note you don't need to write "this," but it's clearer that this is a member field
}
And then in your main method:
for (int i=0;i<14;i++) {
String input = <get input>
josue.setCliockInTime(i, input);
}
Now you can set one value at a time, and that should let you populate all of your fields.

Reading DATE type from text file

I have a text file which looks like this
2017-06-14 7932
2017-06-15 10092
2017-06-16 7626
2017-06-17 7613
2017-06-18 11072
2017-06-19 8286
2017-06-20 9293
I am trying to store the values in an ArrayList.
My Code:
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.io.*;
import java.util.Scanner;
public class Sample2 {
public static void main(String[] args) throws FileNotFoundException {
List<Date> l1 = new ArrayList<Date>();
List<Integer> l2 = new ArrayList<Integer>();
Scanner s = new Scanner(new FileReader("t1.txt"));
while (s.hasNext()) {
l1.add(s.nextInt()); !!!!-----Error Line-----!!!!!!!!
l2.add(s.nextInt());
}
s.close();
System.out.println(l1);
System.out.println(l2);;
}
}
I get the Following Error:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The method add(int, Date) in the type List is not
applicable for the arguments (int)
at Sample2.main(Sample2.java:17)
How do I fix it?
Two suggestions:
Create a small class to hold the date and the int that belong together. Why? See Jon Skeet’s Anti-pattern: parallel collections.
Skip the outdated Date class and use the modern LocalDate instead. It models a date without time-of-day, which is exactly what you need here. It also parses your dates right out of the box with no need for an explicit format, so it’s very convenient for your specific purpose.
Below I have just lumped the code together in one class, you will probably want a design with more classes. I will leave that to you.
public class Sample2 {
private LocalDate date;
private int value2;
public Sample2(LocalDate date, int value2) {
this.date = date;
this.value2 = value2;
}
#Override
public String toString() {
return "\nSample2 [date=" + date + ", value2=" + value2 + "]";
}
public static void main(String[] args) throws FileNotFoundException {
List<Sample2> l = new ArrayList<>();
Scanner s = new Scanner(new FileReader("t1.txt"));
while (s.hasNext()) {
l.add(new Sample2(LocalDate.parse(s.next()), s.nextInt()));
}
s.close();
System.out.println(l);
}
}
The program prints
[
Sample2 [date=2017-06-14, value2=7932],
Sample2 [date=2017-06-15, value2=10092],
Sample2 [date=2017-06-16, value2=7626],
Sample2 [date=2017-06-17, value2=7613],
Sample2 [date=2017-06-18, value2=11072],
Sample2 [date=2017-06-19, value2=8286],
Sample2 [date=2017-06-20, value2=9293]]
I will also leave to you to add getters (you may not need setters) and to find better variable names. You know what the numbers mean.
You need to check for an int by using the nextInt() method.
"else" s.next() will return a String.
This will fix your error:
while (s.hasNext()) {
if (s.hasNextInt()) {
int myInt = s.nextInt();
System.out.println(myInt);
} else {
String dateAsString = s.next();
System.out.println(dateAsString);
}
}
When I run this code, I get:
2017-06-14
7932
2017-06-15
10092
2017-06-16
7626
2017-06-17
7613
2017-06-18
11072
2017-06-19
8286
2017-06-20
9293
You will have to convert your date string to a localDate() or Date()
Can you try with below code
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Scanner;
public class Sample2 {
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
public static void main(String[] args) throws FileNotFoundException {
List<Date> l1 = new ArrayList<Date>();
List<Integer> l2 = new ArrayList<Integer>();
Scanner s = new Scanner(new FileReader("t1.txt"));
while (s.hasNext()) {
l1.add(getDate(s.next()));
l2.add(s.nextInt());
}
s.close();
System.out.println(l1);
System.out.println(l2);
}
private static Date getDate(String next) {
Date date = null;
try {
date = dateFormat.parse(next);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}

static variables appear null outside of main method

Im building a lexical/syntex analyzer for class. The problem I am having is when I try to access my static variable "lexems" or "tokens" from a method besides main they are NULL. When I use them in main (such as the lex.printList method) they are fine and filled with data.
Whats going on???
import java.io.IOException;
import java.util.ArrayList;
public class SyntaxAnalyzer {
public static int pos = 0;
public static ArrayList<String> lexems = new ArrayList<String>();
public static ArrayList<String> tokens = new ArrayList<String>();
public static String nextToken;
public static void main(String[] args) throws IOException {
LexicalAnalysis lex = new LexicalAnalysis();
lex.getFile();
lex.parseText();
ArrayList<String> lexems = lex.getLexems();
lex.printList(lexems);
ArrayList<String> tokens = lex.getTokens();
lex.printList(tokens);
//expr();
lex();
}
static void lex(){
//String lexem = lexems.get(pos);
//System.out.println(lexem);
nextToken = tokens.get(pos);
pos++;
}
}
You are overriding the lexems object with the local one so it is not static variable you are modifying inside main function.
To operate on the static one you should do
/*NOTHING HERE!!*/ lexems = lex.getLexems();
lex.printList(lexems);
...
The same issue with tokens occurs
/*NOTHING HERE!!*/ tokens = lex.getTokens();
lex.printList(tokens);
...
The problems are here:
ArrayList<String> lexems = lex.getLexems();
lex.printList(lexems);
ArrayList<String> tokens = lex.getTokens();
In you main function you do not modify the static variables but local ones (local in the main function).
Just change it to that:
lexems = lex.getLexems();
tokens = lex.getTokens();
You are creating another pair of variables in your main method, which happen to have same names as your static variables, and "overshadow" them within the scope of main method.
To fix it, you should not declare new variables, but initialise the existing ones:
public static void main(String[] args) throws IOException {
LexicalAnalysis lex = new LexicalAnalysis();
lex.getFile();
lex.parseText();
lexems = lex.getLexems();
lex.printList(lexems);
tokens = lex.getTokens();
lex.printList(tokens);
//expr();
lex();
}
This should help make the difference between the scopes used in your code :
public class MyClass{
private static int myInt;
public static void main(String[] args){
int myInt = 6;
printMyInt();
}
static void printMyInt(){ System.out.println(myInt); } // Prints 0 because uses the class field
}

Categories

Resources