10

I'm having trouble putting multiple classes into a single file. For example, when my file looks like:

public class FirstClass() {}
public class SecondClass() {}
public class ThirdClass() {}

I get an error during compilation. I'm not quite sure what's causing this. Any ideas?

Zach Latta
  • 3,251
  • 5
  • 26
  • 40
  • http://stackoverflow.com/questions/4651568/what-is-a-good-practice-to-combine-your-classes – riti Oct 30 '12 at 04:43
  • 11
    *"My professor asked us to turn in our assignments in a single .class file to save him time."* - Your professor is encouraging bad habits and should know better ... – Stephen C Oct 30 '12 at 04:47
  • @rini - that Q&A is about packages ... not about combining multiple classes into one ".java" file. – Stephen C Oct 30 '12 at 04:49
  • Most of the answers implicitly address only multiple top-level classes per file. **You *can* have multiple public classes defined in a single file** -- just not multiple top-level classes. Five years after this question was posted, I've added a [correct, more complete answer](https://stackoverflow.com/a/44806642/202009). – Andy Thomas Jun 28 '17 at 16:45

8 Answers8

23

One Java file can consist of multiple classes with the restriction that only one of them can be public. As soon as you remove public keyword from your classes, you can combine them into a single Java file.

Zach Latta
  • 3,251
  • 5
  • 26
  • 40
Bharat Sinha
  • 13,973
  • 6
  • 39
  • 63
  • 2
    *"with the restriction that only one of them can be public*"...I don't think so. Take a look at [Rectangle2D](http://docs.oracle.com/javase/7/docs/api/java/awt/geom/Rectangle2D.html) for example, it has two inner class, both are public... – MadProgrammer Oct 30 '12 at 05:05
  • 1
    @MadProgrammer : rectangle 2d does not contain a main function. If you have a main function in a class that function should be declared as public and the file should have the name of that public class. But if there is not main(), then you can have any number of classes as public, The OP's class theaterdemo contains main(). – Ashwin Oct 30 '12 at 08:29
  • 1
    It makes no difference, you can have as many public inner classes as you like, they can even be static, but yes, the outer class containing the main method should public. – MadProgrammer Oct 30 '12 at 08:32
  • 2
    Thanks for the brief but comprehensive answer. – Zach Latta Oct 31 '12 at 23:44
  • 1
    @Ashwin And of course someone's edited the question *just* to remove that very important bit of info... –  Sep 13 '18 at 16:16
4

At the risk of spoon-feeding

Please read http://docs.oracle.com/javase/tutorial/java/javaOO/innerclasses.html

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;


public class TheaterWindow extends JFrame
{
    private JPanel pnlAdultTicketPrice, pnlAdultTicketsSold, pnlChildTicketPrice, pnlChildTicketsSold,
        pnlCalculate, pnlMain;
    private JLabel lblAdultTicketPrice, lblAdultTicketsSold, lblChildTicketPrice, lblChildTicketsSold;
    private JTextField txtAdultTicketPrice, txtAdultTicketsSold, txtChildTicketPrice, txtChildTicketsSold;
    private JButton btnCalculate;

    public TheaterWindow()
    {
        // Sets window title
        setTitle("Theater");

        // Sets layout to BorderLayout
        setLayout(new GridLayout(5,1));

        // Specifies what happens when close button is clicked
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Builds the panels
        buildPanels();

        // Add the panels to the frame's content pane
        add(pnlAdultTicketPrice);
        add(pnlChildTicketPrice);
        add(pnlAdultTicketsSold);
        add(pnlChildTicketsSold);
        add(pnlCalculate);

        // Size the frame to fit all of the panels
        pack();

        // Display the window
        setVisible(true);
    }

    private void buildPanels()
    {
        // Creates labels to display instructions
        lblAdultTicketPrice = new JLabel("Adult ticket price");
        lblChildTicketPrice = new JLabel("Child ticket price");
        lblAdultTicketsSold = new JLabel("Adult tickets sold");
        lblChildTicketsSold = new JLabel("Child tickets sold");

        // Creates text fields that are 10 characters wide
        txtAdultTicketPrice = new JTextField(10);
        txtChildTicketPrice = new JTextField(10);
        txtAdultTicketsSold = new JTextField(10);
        txtChildTicketsSold = new JTextField(10);

        // Creates button with caption
        btnCalculate = new JButton("Calculate");

        // Adds action listener to button
        btnCalculate.addActionListener(new CalcButtonListener());

        // Creates panels
        pnlAdultTicketPrice = new JPanel();
        pnlChildTicketPrice = new JPanel();
        pnlAdultTicketsSold = new JPanel();
        pnlChildTicketsSold = new JPanel();
        pnlCalculate = new JPanel();
        pnlMain = new JPanel();

        // Adds elements to their proper panels
        pnlAdultTicketPrice.add(lblAdultTicketPrice);
        pnlAdultTicketPrice.add(txtAdultTicketPrice);
        pnlChildTicketPrice.add(lblChildTicketPrice);
        pnlChildTicketPrice.add(txtChildTicketPrice);
        pnlAdultTicketsSold.add(lblAdultTicketsSold);
        pnlAdultTicketsSold.add(txtAdultTicketsSold);
        pnlChildTicketsSold.add(lblChildTicketsSold);
        pnlChildTicketsSold.add(txtChildTicketsSold);
        pnlCalculate.add(btnCalculate);

        // Adds all of the above panels to a main panel
        pnlMain.add(pnlAdultTicketPrice);
        pnlMain.add(pnlChildTicketPrice);
        pnlMain.add(pnlAdultTicketsSold);
        pnlMain.add(pnlChildTicketsSold);
        pnlMain.add(pnlCalculate);
    }

    private class CalcButtonListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            // Creates object of Theater
            Theater theater = new Theater();

            // Sets the member variables of Theater to the user's input
            theater.setAdultTicketPrice(Double.parseDouble(txtAdultTicketPrice.getText()));
            theater.setChildTicketPrice(Double.parseDouble(txtChildTicketPrice.getText()));
            theater.setAdultTicketsSold(Integer.parseInt(txtAdultTicketsSold.getText()));
            theater.setChildTicketsSold(Integer.parseInt(txtChildTicketsSold.getText()));

            // Creates DecimalFormat object for rounding
            DecimalFormat dollar = new DecimalFormat("#.##");

            // Display the charges.
            JOptionPane.showMessageDialog(null, "Adult ticket gross: $" +
                    Double.valueOf(dollar.format(theater.getAdultGross())) + "\n" +
                    "Child ticket gross: $" + Double.valueOf(dollar.format(theater.getChildGross())) + "\n" +
                    "Adult ticket net: $" + Double.valueOf(dollar.format(theater.getAdultNet())) + "\n" +
                    "Child ticket net: $" + Double.valueOf(dollar.format(theater.getChildNet())) + "\n" +
                    "Total gross: $" + Double.valueOf(dollar.format(theater.getChildGross())) + "\n" +
                    "Total net: $" + Double.valueOf(dollar.format(theater.getTotalNet())));
        }
    }

    public class Theater
    {
        private double PERCENTAGE_KEPT = 0.20;

        private double adultTicketPrice, childTicketPrice;
        private int adultTicketsSold, childTicketsSold;

        public double getAdultGross()
        {
            return getAdultTicketPrice() * getAdultTicketsSold();
        }

        public double getAdultNet()
        {
            return PERCENTAGE_KEPT * getAdultGross();
        }

        public double getAdultTicketPrice()
        {
            return adultTicketPrice;
        }

        public int getAdultTicketsSold()
        {
            return adultTicketsSold;
        }

        public double getChildGross()
        {
            return getChildTicketPrice() * getChildTicketsSold();
        }

        public double getChildNet()
        {
            return PERCENTAGE_KEPT * getChildGross();
        }

        public double getChildTicketPrice()
        {
            return childTicketPrice;
        }

        public int getChildTicketsSold()
        {
            return childTicketsSold;
        }

        public double getTotalGross()
        {
            return getChildGross() + getAdultGross();
        }

        public double getTotalNet()
        {
            return getChildGross() + getChildNet();
        }

        public void setAdultTicketPrice(double adultTicketPrice)
        {
            this.adultTicketPrice = adultTicketPrice;
        }

        public void setAdultTicketsSold(int adultTicketsSold)
        {
            this.adultTicketsSold = adultTicketsSold;
        }

        public void setChildTicketPrice(double childTicketPrice)
        {
            this.childTicketPrice = childTicketPrice;
        }

        public void setChildTicketsSold(int childTicketsSold)
        {
            this.childTicketsSold = childTicketsSold;
        }
    }
}
Arun Manivannan
  • 4,213
  • 3
  • 29
  • 38
2

Yes You can write your all classes in a single .java file, But you must have only one class public(if file name and class name same)

Example:

class A { }

class B { }

class C { }

  • 2
    Yes, but why? and what does that say about the visibility and scope of the other classes b and c? – Andrew S Jan 16 '15 at 05:35
1

I am assuming you are very beginner! Just copy paste all these contents in a single file TheaterDemo.java. And dont forget to remove all the public keyword in the beginning of class declaration.

shriguru nayak
  • 310
  • 1
  • 3
  • 21
1

One Java file can contain at most one top-level public class. That public top-level class can contain any number of public nested classes.

You can eliminate your compiler errors by any of the following approaches:

  • Moving the other classes into their own files. For example: FirstClass.java, SecondClass.java, and ThirdClass.java.
  • Nesting the classes whose name is not the file basename. For example:

    public class FirstClass() {
        public class SecondClass() {}   
        public class ThirdClass() {}
    }
    
  • Removing the public qualifier from all but the one class whose name is the file basename. This approach has become less common after the introduction of nested classes in Java v1.1. For example, in file FirstClass.java, you could have:

    public class FirstClass() {}
    class SecondClass() {}   
    class ThirdClass() {}
    

From the Java Language Specification, section 7.6: Top Level Type Declarations:

If and only if packages are stored in a file system (§7.2), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav) if either of the following is true:

  • The type is referred to by code in other compilation units of the package in which the type is declared.

  • The type is declared public (and therefore is potentially accessible from code in other packages).

Andy Thomas
  • 84,978
  • 11
  • 107
  • 151
0

Just remove public from all other class definition and paste the code into TheaterDemo.java file

public class TheaterDemo
{
    public static void main(String[] args)
    {
        TheaterWindow theaterWindow = new TheaterWindow();
    }
}
//Here class code after removing public

// Here another class code
kosa
  • 65,990
  • 13
  • 130
  • 167
0

I see you have already done that kind of implementation. Please refer

    private class CalcButtonListener implements ActionListener

in your TheaterWindow class.

By doing this, you are creating inner classes i.e. CalcButtonListener is an inner class of TheaterWindow class. Some concept you can extend to other classes.

Yogendra Singh
  • 33,927
  • 6
  • 63
  • 73
  • 1
    *"An inner class can't be defined with public visibility"*...Why not? Make it static and you can even instantiate it. [Rectangle2D.Double](http://docs.oracle.com/javase/7/docs/api/java/awt/geom/Rectangle2D.Double.html) does it? – MadProgrammer Oct 30 '12 at 04:53
  • @MadProgrammer: I meant regular class. I will update the answer. Thanks for the input. – Yogendra Singh Oct 30 '12 at 04:55
  • *"An REGULAR inner class(non static) can't be defined with public"*...Yes it can. Imagine you have a class that has a supporting class declared as a inner class, you may want it to be public so it can be exposed via a getter (for example), but you don't want people to be able to create their own instances. – MadProgrammer Oct 30 '12 at 04:59
  • 1
    Your note is also wrong. You **can** have public inner classes. Next time, make some tests before posting the answer. – Luiggi Mendoza Oct 30 '12 at 04:59
  • @MadProgrammer & LuiggiMedoza: Thank you both. I have not been doing this so thought its not supported. Removed the comment from the answer. – Yogendra Singh Oct 30 '12 at 05:02
  • You got to be careful with what you say and how you say it. I can earn you downvotes ;) – MadProgrammer Oct 30 '12 at 05:09
0

There is no restriction on the number of class files in a java file.

But we can’t have more than one public class per source code file. Also the name of the file must match the name of the public class. Like, a class declared as public class Dog { } must be in a source code file named Dog.java.

And files with no public classes can have a name that does not match any of the classes in the file.