I'm working on a transcript project for school, and it's compiling as if there's an anonymous inner class, but I haven't written any. Why is javac compiling an inner class without there being any inner classes (including enums or exceptions) written? The file in question is SemesterInfo$1.class, compiled from SemesterInfo.java. I've seen similar questions where there actually have been inner classes, but there are none here. I throw one exception from the Java library (UnsupportedOperationException), but it's already defined inside the library (java.lang.UnsupportedOperationException) and is therefore not anonymous or an inner class. My directory is as follows:
02/20/2016 02:03 PM 915 AddResult.class
02/15/2016 09:16 PM 848 AddResult.java
02/20/2016 02:03 PM 1,032 Console.class
02/05/2016 08:27 AM 1,315 Console.java
02/20/2016 02:03 PM 1,624 CourseInfo.class
02/19/2016 10:56 AM 9,203 CourseInfo.java
02/20/2016 02:03 PM 2,244 CourseInfoTester.class
02/17/2016 05:15 PM 2,226 CourseInfoTester.java
01/22/2016 10:55 AM 3,769 Keyboard.class
02/20/2016 02:03 PM 686 SemesterInfo$1.class
02/20/2016 02:03 PM 6,810 SemesterInfo.class
02/20/2016 01:57 PM 36,263 SemesterInfo.java
02/20/2016 02:03 PM 1,350 SemesterInfoTester.class
02/17/2016 11:59 PM 1,050 SemesterInfoTester.java
import java.util.Scanner;
public class SemesterInfo
{
public static int MAX_COURSES = 7;
public static int MAX_CREDITS = 18;
private static String WITHDRAWN = "W";
private static int NOT_FOUND = -1;
protected String name;
protected int creditHours;
protected int completedCourses;
protected int courseCount;
private Scanner input = new Scanner(System.in);
protected CourseInfo[] courseList;
/**********************************************************************************************
* This builds an empty semester using the given name.
**********************************************************************************************/
SemesterInfo(String name)
{
this.name = name;
creditHours = 0;
completedCourses = 0;
courseCount = 0;
courseList = new CourseInfo[MAX_COURSES];
}
/**********************************************************************************************
* This will confirm if a requested semester name is valid. A valid semester must have the
* season as the first word and year as the second word. The year must be between 1900
* and 9999. The season is not currently case sensitive, although it is recommended to
* have the season match Title Case (i.e. "Spring" instead of "spring").
**********************************************************************************************/
public static boolean isValidSemester(String name)
{
final int MIN_YEAR = 1900;
final int MAX_YEAR = 9999;
boolean valid;
String[] words = name.split(" ");
int year;
if (words.length != 2)
{
valid = false;
}
else if (!words[0].equalsIgnoreCase("Summer") && !words[0].equalsIgnoreCase("Fall")
&& !words[0].equalsIgnoreCase("Winter") && !words[0].equalsIgnoreCase("Spring"))
{
valid = false;
}
else
{
try
{
year = Integer.parseInt(words[1]);
if (year < MIN_YEAR || year > MAX_YEAR)
{
valid = false;
}
else
{
valid = true;
}
}
catch (NumberFormatException e)
{
valid = false;
}
}
return valid;
}
/**********************************************************************************************
* This will add a new course to the semester's list. If the current semester is already full
* of courses, the method will return a false value.
**********************************************************************************************/
public AddResult addCourse(CourseInfo course)
{
AddResult result;
if (completedCourses >= MAX_COURSES)
{
result = AddResult.EXCEEDS_COURSE_MAX;
}
else if (creditHours + course.creditHours > MAX_CREDITS)
{
result = AddResult.EXCEEDS_CREDIT_MAX;
}
else if (searchCourse(course.prefix, course.courseNumber) != NOT_FOUND)
{
result = AddResult.REDUNDANT;
}
else
{
courseList[courseCount] = course;
if (!course.wasWithdrawn())
{
completedCourses++;
creditHours += course.creditHours;
}
courseCount++;
result = AddResult.SUCCESS;
}
return result;
}
/**********************************************************************************************
* This removes a course by name if it exists in the course list, and returns whether the
* course was successfully removed.
**********************************************************************************************/
public boolean removeCourse(String prefix, String number)
{
boolean removed;
int location = searchCourse(prefix, number);
if (location == NOT_FOUND)
{
removed = false;
}
else
{
if (!courseList[location].wasWithdrawn())
{
completedCourses--;
creditHours -= courseList[location].creditHours;
}
courseCount--;
for (int i = location; location < courseCount; i++)
{
courseList[i] = courseList[i+1];
}
removed = true;
}
return removed;
}
/**********************************************************************************************
* This will allow a course to be withdrawn after it's been entered. Once a course has been
* withdrawn, it can't be re-added, but will stay on the transcript as withdrawn.
**********************************************************************************************/
public boolean withdrawCourse(String prefix, String number)
{
boolean withdrawn;
int location = searchCourse(prefix, number);
if (location == NOT_FOUND)
{
withdrawn = false;
}
//This can't be a combined check in case location doesn't exist (-1 index)
else if (courseList[location].wasWithdrawn())
{
withdrawn = false;
}
else
{
creditHours -= courseList[location].creditHours;
completedCourses--;
courseList[location].withdraw();
withdrawn = true;
}
return withdrawn;
}
/**********************************************************************************************
* This will search the course list for the title of the course given, and returns the index
* of the course. If the course isn't found, -1 is returned.
**********************************************************************************************/
public int searchCourse(String prefix, String number)
{
int index;
boolean found = false;
for (index = 0; index < courseCount && !found; index++)
{
if (courseList[index].prefix.equalsIgnoreCase(prefix)
&& courseList[index].courseNumber.equalsIgnoreCase(number))
{
found = true;
}
}
if (!found)
{
index = 0;
}
return (index - 1);
}
/**********************************************************************************************
* This will prompt the user for the list of courses taken in the semester, using the console
* for input and output. This method then creates Course objects for each course created,
* and adds it to the SemesterInfo object using the addCourse method.
**********************************************************************************************/
public void promptCourseList(String quitStr) throws UnsupportedOperationException
{
final int MAX_PREFIX_LEN = 3;
final int MAX_COURSENUM_LEN = 4;
AddResult result;
CourseInfo course;
String prefix;
String number;
double grade;
String gradeStr;
int credits;
boolean withdrawn;
if (completedCourses == MAX_COURSES)
{
System.out.println("Student is already taking the maximum number of courses!\n");
}
else if (creditHours == MAX_CREDITS)
{
System.out.println("Student is already taking the maximum number of credits!\n");
}
else
{
System.out.print("\tEnter a course prefix (\"" + quitStr + "\" when done): ");
prefix = input.nextLine().toUpperCase();
while (!prefix.equalsIgnoreCase(quitStr) && completedCourses < MAX_COURSES)
{
withdrawn = false;
while (prefix.isEmpty() || prefix.length() > MAX_PREFIX_LEN)
{
System.out.print("\tInvalid prefix.\nEnter a course prefix (1-" + MAX_PREFIX_LEN
+ " characters): ");
prefix = input.nextLine().toUpperCase();
}
System.out.print("\tEnter a course number: ");
number = input.nextLine().toUpperCase();
while (number.isEmpty() || number.length() > MAX_COURSENUM_LEN)
{
System.out.print("\tInvalid number.\nEnter a course number (1-"
+ MAX_COURSENUM_LEN + " characters): ");
number = input.nextLine().toUpperCase();
}
System.out.print("\tEnter credit hours: ");
credits = Integer.parseInt(input.nextLine());
while (credits < CourseInfo.MIN_CREDITS || credits > CourseInfo.MAX_CREDITS)
{
System.out.print("\tInvalid number.\nEnter credit hours (1 - "
+ CourseInfo.MAX_CREDITS + "): ");
credits = Integer.parseInt(input.nextLine());
}
System.out.print("\tEnter grade point (\"" + WITHDRAWN + "\" if withdrawn): ");
gradeStr = input.nextLine();
if (gradeStr.equalsIgnoreCase(WITHDRAWN))
{
withdrawn = true;
grade = CourseInfo.MIN_GRADE_POINT;
}
else
{
try
{
grade = Double.parseDouble(gradeStr);
}
catch (NumberFormatException e)
{
grade = CourseInfo.MIN_GRADE_POINT - 1;
}
}
while (grade < CourseInfo.MIN_GRADE_POINT || grade > CourseInfo.MAX_GRADE_POINT)
{
if (gradeStr.equalsIgnoreCase(WITHDRAWN))
{
withdrawn = true;
grade = CourseInfo.MIN_GRADE_POINT;
}
else
{
try
{
grade = Double.parseDouble(gradeStr);
}
catch (NumberFormatException e)
{
grade = CourseInfo.MIN_GRADE_POINT - 1;
}
}
if (grade < CourseInfo.MIN_GRADE_POINT || grade > CourseInfo.MAX_GRADE_POINT)
{
System.out.print("\tInvalid number.\nEnter grade point (\"" + WITHDRAWN
+ "\" or 0.0 - " + CourseInfo.MAX_GRADE_POINT + "): ");
grade = Double.parseDouble(input.nextLine());
}
}
if (withdrawn)
{
course = new CourseInfo(prefix, number, credits);
}
else
{
course = new CourseInfo(prefix, number, grade, credits);
}
result = addCourse(course);
switch (result) {
case SUCCESS:
System.out.println("\tSuccessfully added " + course.prefix + "-"
+ course.courseNumber);
break;
case REDUNDANT:
System.out.println("\tCourse was already entered.");
break;
case EXCEEDS_COURSE_MAX: //Shouldn't happen, since prompting should end first
System.out.println("\tStudent is already taking a full course load!");
break;
case EXCEEDS_CREDIT_MAX:
System.out.println("\tStudent is already taking too many credits ("
+ creditHours + " of " + MAX_CREDITS + ")!");
break;
default:
throw new UnsupportedOperationException("\tUnknown error occurred while "
+ "adding course: " + result);
}
if (completedCourses < MAX_COURSES)
{
System.out.print("\n\tEnter a course prefix (\"" + quitStr + "\" when done): ");
prefix = input.nextLine().toUpperCase();
}
}
}
}
/**********************************************************************************************
* This will calculate the GPA of all courses currently in the semester.
**********************************************************************************************/
public double calcGPA()
{
double totalGradePoint = 0.0;
for (int i = 0; i < courseCount; i++)
{
if (!courseList[i].wasWithdrawn())
{
totalGradePoint += courseList[i].calcGradePoint();
}
}
return (totalGradePoint / creditHours);
}
/**********************************************************************************************
* This will display the entire semester's course list and GPA in tabular format, centered to
* a window 80 characters wide.
**********************************************************************************************/
public void displaySemester()
{
String gpaString;
if (courseCount == 0)
{
System.out.println(" No courses were taken this semester.");
}
else
{
System.out.println(" " + name);
System.out.println(" Course Grade Credits Grade Point");
for (int i = 0; i < courseCount; i++)
{
System.out.println(" " + courseList[i].toString());
}
if (completedCourses < 1)
{
gpaString = "GPA: N/A";
}
else
{
gpaString = String.format("GPA: %4.2f", calcGPA());
}
System.out.println(" " + gpaString);
}
System.out.println();
}
/**********************************************************************************************
* This method will display the semester details on a single line in tabular format for the
* following expected table example:
* Semester Date Courses Credits GPA
* Fall 2016 4 15 4.00
* There is no padding on either side of the string, and no new line at end of line.
**********************************************************************************************/
@Override
public String toString()
{
String gpa;
if (completedCourses != 0)
{
gpa = String.format("%4.2f", calcGPA());
}
else
{
gpa = "N/A";
}
return String.format("%-13s %1d %2d %4s", name, completedCourses,
creditHours, gpa);
}
}
/**************************************************************************************************
* Program Description: This class holds the information for a specific course.
**************************************************************************************************/
public class CourseInfo
{
public static int MIN_CREDITS = 1;
public static int MAX_CREDITS = 4;
public static double MIN_GRADE_POINT = 0.0;
public static double MAX_GRADE_POINT = 4.0;
protected String prefix;
protected String courseNumber;
protected int creditHours;
protected double grade;
private boolean withdrawn;
/**********************************************************************************************
* This constructor will assign the course prefix, course number, grade and credits when a
* course was not withdrawn.
**********************************************************************************************/
public CourseInfo(String prefix, String number, double grade, int credits)
{
this.prefix = prefix;
courseNumber = number;
this.grade = grade;
creditHours = credits;
withdrawn = false;
}
/**********************************************************************************************
* This constructor will assign the course prefix, course number, grade and credits when a
* course was not withdrawn.
**********************************************************************************************/
public CourseInfo(String prefix, String number, int credits)
{
this.prefix = prefix;
courseNumber = number;
grade = 0.0;
creditHours = credits;
withdrawn = true;
}
/**********************************************************************************************
* This method will calculate the grade point, multiplying the credit hours by the grade.
**********************************************************************************************/
public double calcGradePoint()
{
return (creditHours * grade);
}
/**********************************************************************************************
* This method will tell whether the course was withdrawn or not.
**********************************************************************************************/
public boolean wasWithdrawn()
{
return withdrawn;
}
/**********************************************************************************************
* This method will withdraw the course
**********************************************************************************************/
public void withdraw()
{
withdrawn = true;
grade = 0.0;
creditHours = 0;
}
/**********************************************************************************************
* This method will display the course details on a single line in tabular format for the
* following expected table example:
* Course Grade Credits Grade Point
* CSC-264 4.0 4 16.00
* There is no padding on either side of the string, and no new line at end of line.
**********************************************************************************************/
@Override
public String toString()
{
String str;
if (wasWithdrawn())
{
str = String.format("%3s-%-4s W %1d N/A", prefix,
courseNumber, creditHours);
}
else
{
str = String.format("%3s-%-4s %4.2f %1d %5.2f", prefix,
courseNumber, grade, creditHours, calcGradePoint());
}
return str;
}
}
public enum AddResult
{
SUCCESS, //Course/Semester was added successfully
EXCEEDS_COURSE_MAX, //Student is already taking too many courses
EXCEEDS_CREDIT_MAX, //Student is already taking too many credits
REDUNDANT //Course/Semester already exists
}
This is caused by your switch
statement switching on an enum
value.
The $1
class file contains a static helper array called a switchmap (a kind of lookup table) to determine at runtime to which bytecode location to jump for each case
, based on the enum ordinals. If you decompile it, the beginning looks like this:
$ javap -c SemesterInfo$1.class
Compiled from "SemesterInfo.java"
class SemesterInfo$1 {
static final int[] $SwitchMap$AddResult;
static {};
Code:
0: invokestatic #1 // Method AddResult.values:()[LAddResult;
... Additional code which initializes the array (static initializer)
See also Java enum and additional class files:
Javac 1.5 and 1.6 [and most likely beyond] create an additional synthetic class each time you use a switch on an enum
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With