This week's book giveaway is in the NodeJS forum.
We're giving away four copies of Serverless Applications with Node.js and have Slobodan Stojanovic & Aleksandar Simovic on-line!
See this thread for details.
Win a copy of Serverless Applications with Node.js this week in the NodeJS forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Bear Bibeault
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Junilu Lacar
  • Paul Clapham
  • Knute Snortum
Saloon Keepers:
  • Stephan van Hulst
  • Ron McLeod
  • Tim Moores
  • salvin francis
  • Carey Brown
Bartenders:
  • Tim Holloway
  • Frits Walraven
  • Vijitha Kumara

Static Methods Confusion  RSS feed

 
Ranch Hand
Posts: 120
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For some reason I cannot seem to get my head wrapped around "static" references. I have a class that I created and my IDE complains about static references. I don't understand how to make the class non-static since I expect to have multiple instances. Here is the class:

My IDE wants to declare a static version. I don't see this on other classes that I've created so why this one? It also wants the reference to chooser.ShowDialog to be "accessed in a static way." I'm guessing that warning is because it thinks the class itself should be static. Can someone explain why this class cannot be "non-static?" TIA.
 
Sheriff
Posts: 13392
221
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It's a warning that informs you of poor coding form.

See https://docs.oracle.com/javase/8/docs/api/javax/swing/JColorChooser.html#showDialog-java.awt.Component-java.lang.String-java.awt.Color-

the showDialog() method is a static method. You are calling it using an object reference (non-static) with chooser.showDialog(). This is poor form because while Java allows this construct, it makes showDialog() look like an instance method (non-static) rather than a class method (static).  

If you did this: JColorChooser.showDialog(...) instead, that would be using a static context and the warning your IDE gives you now will go away.

 
Sam Ritter
Ranch Hand
Posts: 120
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks. In this case if I use JColorChooser.showDialog, how would I set the location? Eventually I will need to set other customizations before displaying the dialog. I need the instance of JColorChooser to do that, right? Obviously I am still missing something.
 
Sam Ritter
Ranch Hand
Posts: 120
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Could I declare chooser as static? Is it static to this particular instance of the JFrame? Since there would be only 1 chooser per ColorChooser instance I guess that would be OK.
 
Marshal
Posts: 63849
209
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You are probably better off deleting chooser altogether and using the static method properly: JColourChooser.showXXXDialog(...); as Junilu told you earlier.
I can also see other things I don't like. I don't think your application IS‑A JFrame, but is does HAVE‑A JFrame and it does USE‑A JFrame. So I think there are very few places where it is actually good design to extend a display class. I also don't think a frame should implement action listener or similar. Make a separate action listener class λ and add that to the appropriate button etc.
 
Sam Ritter
Ranch Hand
Posts: 120
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks but that does not address the core question. If I use it that way, how do I customize the JColorChooser display? I still somehow need the instance to set parameters.
 
Campbell Ritchie
Marshal
Posts: 63849
209
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If it is a static method, it ignores all instance fields and value and data (it has to, since a static method can never access such values.
Have you been through the Java™ Tutorials?
 
Sam Ritter
Ranch Hand
Posts: 120
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes but I think we are talking abut 2 different things at this point. I get the static part but I don't get how to set the parameters if I don't get the instance (chooser=new).
 
Campbell Ritchie
Marshal
Posts: 63849
209
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can't set anything via the instances. A static method cannot access instance data, so any information required by the method has to be passed as an argument:- Color c = JColorChooser.showDialog(myPanel, "Colour Please:-", "Color.SKY_BLUE_PINK); Beware: that method can return null. A colour chooser is different from a file chooser where you usually create an instance first.
 
Sheriff
Posts: 24295
55
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Sam Ritter wrote:In this case if I use JColorChooser.showDialog, how would I set the location? Eventually I will need to set other customizations before displaying the dialog. I need the instance of JColorChooser to do that, right? Obviously I am still missing something.



When you find yourself asking that kind of question, your Google keywords should be JColorChooser tutorial.

Hopefully the first link you get back from Mr. Google will be an Oracle tutorial. Like this one: How to Use Color Choosers.
 
Sam Ritter
Ranch Hand
Posts: 120
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I've already looked at that and that is what got me where I am.
 
Sam Ritter
Ranch Hand
Posts: 120
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I figured it out but I don't understand it. The problem was that color was declared locally. I added the color declaration in the class itself rather than in the action listenter and that solved the problem.
 
Sam Ritter
Ranch Hand
Posts: 120
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Nope, that didn't really fix it either. Still working on it.
 
Master Rancher
Posts: 3028
21
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

The above code creates a JColorChooser component that can be added to a JDialog.


The above code creates a JDialog with a JColorChooser component added to the dialog.

In this case the static method is really a convenience method. It will:

1. create a JDialog
2. create a JColorChooser component and add it to the dialog
3. add listeners to the components on the color chooser
4. show the modal dialog
5. close the dialog when a color is selected and return the color value for you

The reason the method is static, is because you don't need an instance of the JColorChooser to invoke the method. The method itself will create the instance.

If you don't like the default location of the dialog then you can't take advantage of the JColorChooser.showDialog(...) method.

Instead you need to manually code the above 5 basic steps. Once you create the child dialog (note child windows should be dialogs, not frames), then you can set the location yourself.

As has already been suggested you need to read the Swing tutorial on How to Use Color Choosers.

The code you posted basically does nothing. The ColorChooserDemo code from the tutorial shows you the minimal amount of code needed to display the color chooser manually. Download the code and play with it.

Now you need to decide if it is worth it just to display the chooser at location (0, 0).
 
Sam Ritter
Ranch Hand
Posts: 120
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have multiple buttons that need to use a different instance of the dialog. I used the suggested JFrame but I guess I need to rewrite it to use a different JDialog for each button so it is not static. When I choose a color, it changes all the buttons not just the one being used. Back to the drawing board.
 
Campbell Ritchie
Marshal
Posts: 63849
209
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Sam Ritter wrote:. . . . When I choose a color, it changes all the buttons not just the one being used. . . . .

That is because you have declared the Color at too high a level. Call setBackground(...) on the individual buttons, and only from one action listener.
 
Sam Ritter
Ranch Hand
Posts: 120
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, I need to rewrite the code.
 
Rob Camick
Master Rancher
Posts: 3028
21
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
15 replies into the question and I still have no idea what your real requirement is.

First you ask a question about "static". Now your question is about buttons.

I have multiple buttons that need to use a different instance of the dialog.


I'm not sure why you think you need a different instance. A JColorChooser is a temporary dialog. You display the dialog get the selected color and the dialog closes. You can use the JColorChooser.showDialog(...) method again. Yes internally the color choose may create a new instance of the JColorChooser class but that is of no concern to you. All you want is to get a selected color.

When I choose a color, it changes all the buttons not just the one being used


That statement makes no sense. If you invoke setForeground(...) or setBackground(...) on a single component, then only the color of that component should change.

In any case, where is your SSCCE demonstrating this problem?

Start with a JFrame with multiple buttons.

Then create an ActionListener that does the following:

1. Use the JColorChooser.ShowDialog(...) method to display the color chooser
2. get the button that was clicked by using the getSource() method of the ActionEvent
3. set the foreground of the button to the color selected

This is a generic listener that can be added to all three buttons.

Get this basic concept working and then fix your real program.
 
Sam Ritter
Ranch Hand
Posts: 120
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry about the confusion. It started as what I thought was a simple issue of static methods. It evolved into more details about what I was doing. Responses made it clear my entire approach was wrong (i.e. poor programming practices). I'm working on rewriting the code following the suggestions here, so as far as I'm concerned this question has been answered. Thanks to all.
 
Campbell Ritchie
Marshal
Posts: 63849
209
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That's a pleasure Please push the resolved button .
 
Author
Posts: 974
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Sam Ritter wrote:Sorry about the confusion. It started as what I thought was a simple issue of static methods. It evolved into more details about what I was doing. Responses made it clear my entire approach was wrong (i.e. poor programming practices).



Well, part of it is that you are confused about calling static methods. You don't seem to realize that doing this......is exactly the same as doing
The fact the first one instantiates a specific instance of JColorChooser doesn't change anything, except add confusion that it might somehow be relevant to the showDialog() method when it's not.

The reason people (and also the IDE) recommend you do it the second way and not the first way is not because it works any better (which it doesn't—it works exactly the same) but because it's less confusing.
 
Campbell Ritchie
Marshal
Posts: 63849
209
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Brian Cole wrote:. . . The reason people (and also the IDE) recommend you do it the second way and not the first way is not because it works any better (which it doesn't—it works exactly the same) but because it's less confusing.

Assuming each of the Animal, Lion, and Elephant classes has a method called staticMethod(), which one is actually executed?
 
Greenhorn
Posts: 23
IntelliJ IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello, Ritchie.

Campbell Ritchie wrote:



Why would you want to code something like this?  


 
Junilu Lacar
Sheriff
Posts: 13392
221
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Ricky Bee wrote:

Why would you want to code something like this?  


Because inheritance, polymorphism, and Liskov Substitution Principle

Campbell is trying to point out an example where a call using a object reference instead of a class reference actually does more than just make the code confusing -- binding of calls to static methods is done at compile time whereas binding of calls to instance methods is at run time.
 
Brian Cole
Author
Posts: 974
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Junilu Lacar wrote:Campbell is trying to point out an example where a call using a object reference instead of a class reference actually does more than just make the code confusing


But it doesn't. In Campbell's example all the Lion and Elephant instances are doing is trying to cause more confusion. The confusion is intentional, of course, but it would have been clearer to just write Animal.staticMethod(...) and be done with it.

I'm not saying that calling instanceVariable.staticMethod() is always exactly the same as ClassName.staticMethod() for all contrived examples, because it's not if instanceVariable is null (although early compilers had a bug that missed this) but it is indeed the same in this particular JColorChooser.showDialog(...) case.
 
Ricky Bee
Greenhorn
Posts: 23
IntelliJ IDE Java Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Brian Cole wrote:

Junilu Lacar wrote:Campbell is trying to point out an example where a call using a object reference instead of a class reference actually does more than just make the code confusing


...  all the Lion and Elephant instances are doing is trying to cause more confusion. The confusion is intentional, of course, but it would have been clearer to just write Animal.staticMethod(...) and be done with it.



Actually, I value that kind of intentional induced confusion - it is one of the great things about the Ranch. No direct answers provided, but answers that will make you think about the problem (and context) while "gently" pointing out a way.

There was certainly a lesson to be learned in Campbell's answer (and I thank him for it), but let me rephrase my previous question (and steer it a little from the inheritance of a static method problem which originated it in the first place): is such a structure a common-place in Java programing? I mean, is it normal to instantiate an object from a superclass and then pass it an object from a subclass?  That was what left me thinking...

By the way, thanks Junilu, for another awesome link.  

 
Rancher
Posts: 3127
110
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
hi Ricky,

for classes I seldomly use the construct: A a = new B(). But for interfaces it is very common:

List<...> myList = new ArrayList<>();

What everybody will tell you is that with such a construct, it is then easy to change your mind later about the actual type of List used. You could say, List<...> myList = new LunkedList<>(); and the rest of your program will still function. But I can't remember ever having changed such a concrete class, so it is more theoretical than actual for me.

But if you inspect the API, you will see many methods that will return an instance of type interface, without specifying what particular implementation is returned. For instance, the method Collectors.groupingBy returns a Map, not specifying what Map that would be (although there is an option to specify that kind of Map).

There IS a slight difference, though. myList can only make use of methods that are defined in the interface List. But some implementations of List have some additional methods, that are then unavailable. For instance, a TreeSet contains the very handy method floor(...). That method is, for good reasons, not available in the interface Set, so if you want to use that method you have to use a construct like NavigableSet<..> set = new TreeSet<>();
(NavigableSet is itself an interface, by the way).

I always instatiate JFileChooser, so that I can give each instance its own filefilter, and each will remember the last directory visited.

Lastly: since java 10 you can call (nearly everything) a var: var hup = <some complicated construction perhaps>, and not worry anymore about what actual type var is. I use it more and more, and it is very convenient.
 
Brian Cole
Author
Posts: 974
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Ricky Bee wrote:but let me rephrase my previous question (and steer it a little from the inheritance of a static method problem which originated it in the first place):


FYI, one should be careful using the term inheritance with static methods. Which is not to say that a subclass can't inherit static methods, because they often do, but it's best to be precise.

In Campbell Ritchie's example, for example, the Lion class does not inherit the method staticMethod() from Animal because it's hidden by its own implementation of staticMethod(). Here hidden is a formal term defined by §8.4.8.2 of the Java Language Specification. (See also the first sentence of §8.4.8.)

Ricky Bee wrote:is such a structure a common-place in Java programing? I mean, is it normal to instantiate an object from a superclass and then pass it an object from a subclass?


I would say it's somewhat common. For example, in my code I often write
Now this isn't quite the same, because List is an interface and not a class, but the concept is the same.
I want the rest of my code to treat myList as a generic List without presuming any specific implementation. Then later I can easily change the implementation from ArrayList to something else (such as LinkedList) if I want.

To use Campbell Ritchie's example...
...it wouldn't be unusual to do
and it would be even less unusual to use a Collection instead of an array. Consider
where it's kind of happening twice. The List's type parameter is Animal but the each element of myList is a some subclass of Animal. And also the type of myList is List but the asList() method will return a particular implementation of List.

In swing this of course happens all the time, with java.awt.Component, javax.swing.JComponent, and all the subclasses of JComponent. When you write myPanel.add(new JButton("text")) the type of the argument is Component but you're passing it instance of JButton. And calling myPanel.getComponents() returns an array of type Component[] but each element of the array will be some particular subclass of Component. (But this isn't quite what you were asking.)
 
Campbell Ritchie
Marshal
Posts: 63849
209
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Brian Cole wrote:. . . . it would have been clearer to just write Animal.staticMethod(...) and be done with it. . . .

Yes, of course it is easier to get it right first time and use the correct code, but as Junilu said, I am trying to point out a pitfall, where the semantics of the call on an instance is different from the correct way to call a static method.[ It doesn't work exactly the same now. Yes, of course I was intending to confuse things, but also to bring the confusion to people's notice.

it's not if instanceVariable is null  . . .

You can still write rubbish like...and it will both compile and run with the expected result.
 
Campbell Ritchie
Marshal
Posts: 63849
209
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Ricky Bee wrote:. . . is such a structure a common-place in Java programing? I mean, is it normal to instantiate an object from a superclass and then pass it an object from a subclass? . . .

As Junilu Piet and Brian have told you already, yes.
 
Brian Cole
Author
Posts: 974
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:You can still write rubbish like...and it will both compile and run with the expected result.


I agree. In fact the JLS shows this nifty example:
What I was trying to get at was there was, at one point in the distant past (for Java), a time when the javac compiler was handling nullInstance.staticMethod(...) incorrectly w.r.t. the JLS.

When this was discovered they either changed the compiler or changed the JLS, but I can't find any corroborating details. I've spent a few minutes googling and have struck out. I guess it's possible it never happened and I made it up.

it would have been clearer to just write Animal.staticMethod(...) and be done with it


I realized what you were doing. In saying this I was not trying to imply otherwise, was just trying to answer your "which one is actually executed?" question for the benefit of others. I apologize for being less than clear.
 
Campbell Ritchie
Marshal
Posts: 63849
209
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Brian Cole wrote:. . . In fact the JLS shows this nifty example: . . .

That could have shown return this; or return new Test3(); both of which would have constituted calling a static method on an instance reference.
By the way: which section in the JLS?

I apologize for being less than clear.

Apology accepted
 
Paul Clapham
Sheriff
Posts: 24295
55
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Ricky Bee wrote:
Why would you want to code something like this?  



Beyond what the others have already said (I think), you will also see code like this:



Here I'm thinking of a static method in the AnimalFactory class which in this particular case returns a Lion object but in other cases could return other subclasses of Animal.
 
Brian Cole
Author
Posts: 974
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:That could have shown return this; or return new Test3();


The point is that the method is called, so any side-effects do happen, but what value it returns is irrelevant.

By the way: which section in the JLS?


It's in §15.11.1. (BTW, I happen to be looking at the Java SE 7 edition of the JLS.)
 
Campbell Ritchie
Marshal
Posts: 63849
209
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Brian Cole wrote:. . . . (BTW, I happen to be looking at the Java SE 7 edition of the JLS.)

Thank you It woiuld appear to be 15.11.1 in the Java12 version, too.
 
And then we all jump out and yell "surprise! we got you this tiny ad!"
global solutions you can do at home or in your backyard
https://www.kickstarter.com/projects/paulwheaton/better-world-boo
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!