I have two classes:
public jComboBox() {
... // this is a autocomplete jComboBox btw
...
combo.addItemListener(new ItemListener(){
public void itemStateChanged(ItemEvent ie) {
if(ie.getStateChange() == 1) {
String selectedItem = (String)getSelectedItem();
randomMethod(selectedItem);
}
}
});
}
private void randomMethod(String selectedItem){
someClass sc = new someClass();
String randomString = selectedItem;
sc.getRandomString(randomString);
}
and
public someClass() {
...
...
}
public void getRandomString(String randomString){
defaultTableModel.setRowCount(0);
.. do-something ..
}
Is this method fine? If not, I need some alternative on this one, because i'm having problems for example, using defaultTableModel.setRowCount(0) because the table wont empty, not unless I put the setRowCount(0) on other methods inside someClass class.
Basic java access specifier stuff..... how are you calling this private method getRandomString from randomMethod()? the visibility of private method of a class is only the class, not anywhere else. Therefore, your following code:
private void randomMethod(String selectedItem){
someClass sc = new someClass();
String randomString = selectedItem;
fs.getRandomString(randomString); // This will not work
}
is not going to work because of the access specifier private. If you can allow the access rights to be specific to the package you have, you can change it to:
protected void getRandromString(String randromString) {...}
Just to demonstrate what I mean:
package com.stackoverflow.solutionmaker;
public class Aclass {
public Aclass(){
somePrivMethod();
}
public void aMethod(){
System.out.println("Can see me from anywehre bcoz I am public");
}
private void somePrivMethod(){
System.out.println("Cannot find me from anywhere because I am private t Aclass");
}
}
Now the runner class:
package com.stackoverflow.solutionmaker;
public class StackOverflowSolutionsRunner {
public static void main(String[] args) {
Aclass aClass = new Aclass(); // It will display"Cannot find me from anywhere because I am private t Aclass"
aClass.aMethod(); // It will display "Can see me from anywehre bcoz I am public
aClass.somePrivMethod(); // Will throw a compile-time error
}
}
A good exercise for you now to compile these two from command line and see what error message you get. Alternatively, using Eclipse smart IDE or Jcreator, you can see that your private access specifier is causing red messages to appear.
Related
I am writing a testing framework using Gauge.
I want some initilization logic performed in one class, and the steps logic to reuse it, like this:
public class A {
protected String property = "";
#BeforeSpec
public void init(){
property = "hello";
}
}
public class B extends A {
#Step("...")
public void verifyProperty() {
assertEquals(property, "hello");
}
}
I can't seem to be able to achieve this. When performing the steps, the "property" is always null.
Placing the #BeforeSpec in class B and calling super.init() works, but I would like to avoid having this call in every test class that extends A.
Has anyone encountered and solved such an issue?
Try to use a static variable:
public class A {
public static String property = "";
#BeforeSpec
public void init(){
property = "hello";
}
}
public class B {
#Step("...")
public void verifyProperty() {
assertEquals(A.property, "hello");
}
}
I have two classes and one interface.
Interface:
public interface MyBirthdayEvent {
void itsMyBirthday();
}
First class:
public class MyBirthdayButton
{
public void addOnClickedListener(MyBirthdayEvent mbe){}
}
Second class:
public class MyBirthday {
private MyBirthdayButton myBirthdayButton = new MyBirthdayButton();
MyBirthday() {
myBirthdayButton.addOnClickedListener(new MyBirthdayEvent() {
public void itsMyBirthday() {
System.out.println("Happy Birthday");
}
});
}
}
Then in main, I have this:
public class TestThisStuff {
public static void main(String[] args) {
MyBirthday myBirthday = new MyBirthday();
}
}
As can be seen from the code, I am using an anonymous class in the MyBirthday constructor. In doing so, I am trying to get the string "Happy Birthday" to print to the console.
My problem is, when I call the MyBirthday constructor in main by making a new myBirthday object, I am not seeing the string "Happy Birthday" print to the console. Shouldn't it print to the console? If not, what I am doing wrong?
What you can do is this:
public interface MyBirthdayEvent {
void itsMyBirthday();
default void invoke() {
itsMyBirthday();
}
}
...
public class MyBirthdayButton
{
public void addOnClickedListener(MyBirthdayEvent mbe){
mbe.invoke();
}
}
...
Also, it will work without it, but use a lambda rather than an anonymous inner class. This looks much better.
MyBirthday() {
myBirthdayButton.addOnClickedListener(() ->
System.out.println("Happy Birthday"));
}
you can move System.out.println("some words")statement to your MyBirthdayEventconstructor
it didn't show in your console because you haven't invoke the method
I have the following class structure. I would like to know how can I jump in eclipse to the actual implementation of th gethod printVar().
If I hover (hold down STRG) over the 2 method calls in main and click open implementation I get both Classes displayed. Is there a way to directly jump to the implementation in class B for this method call w.getWrapperVar().printVar()
public class A {
private String var;
public A(String a){
this.var=a;
}
public void printVar(){
System.out.println("class A print: " + this.var);
}
}
public class B extends A{
private String var;
public B(String a){
super(a);
this.var=a;
}
#Override
public void printVar(){
System.out.println("class B print: " + this.var);
}
}
public class Wrapper {
private B wrapperVar;
private A wrapperVar2;
public Wrapper(String var){
this.wrapperVar = new B(var);
this.wrapperVar2 = new A(var);
}
// explicit Return Class A
public A getWrapperVar(){
return this.wrapperVar;
}
public A getWrapperVar2(){
return this.wrapperVar2;
}
}
public class main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Wrapper w = new Wrapper("value");
w.getWrapperVar().printVar();
w.getWrapperVar2().printVar();
}
}
Eclipse doesn't know that the implementation class is B, so it can't take you directly to B.
However, you can click on printVar and press Ctrl-G to search for all methods that might be the actual implementation.
After selecting a method call you can hit the F3 function key. This action will take you to the definition of the method. This definition may be in an interface.
When you are in that file you may want to hit Ctrl+T. This will bring up a type hierarchy showing the classes that implement the method you were looking for.
Hope this helps.
So I have small interface
public interface IPlayersStorage
{
// other methods...
public boolean addException(final String nick);
// other methods...
}
and class "PlayersStorage" that implements it: (only used part)
public class PlayersStorage implements IPlayersStorage
{
private static final PlayersStorage inst = new PlayersStorage();
private final Set<String> exceptions = new HashSet<>(50);
#Override
public boolean addException(final String nick)
{
return ! this.exceptions.add(nick);
}
public static PlayersStorage getStorage()
{
return inst;
}
}
And in some place I use that method using that code:
for (final String player : this.cfg.getStringList("Exceptions"))
{
PlayersStorage.getStorage().addException(player);
}
And ProGuard change it to:
for (Iterator localIterator1 = this.cfg.getStringList("Exceptions").iterator(); localIterator1.hasNext();)
{
localIterator1.next();
PlayersStorage.getStorage(); // it's get object, but don't do anything with it...
}
The only possible fix that I found, is add static method to PlayersStorage
public static boolean staticAddException(final String nick)
{
return inst.addException(nick);
}
And then use it (instead of old code)
for (final String player : this.cfg.getStringList("Exceptions"))
{
PlayersStorage.staticAddException(player);
}
Then works... (ProGuard keep method call) but adding static methods for every method from interface isn't good idea.
ProGuard only removes method invocations if they don't have any effect (doesn't seem to be the case here), or if you have specified -assumenosideffects for the methods. You should check your configuration and remove any such option.
Alternatively, your decompiler may be having problems decompiling the code. You should then check the actual bytecode with javap -c.
I work on a game-like system. Users can submit .class and .java files for customized behaviour. Some objects are delivered to the user via callback, but if the user can construct these object himself (with custom parameters), it would mean an advantage to him. I will disallow reflection for the user and seal my packages. I can get this working if I abandon all package structure (and make the constructors package-private), but I would like not to do so.
Here is an example:
sscce.mycode.a.SomeClass.java:
package sscce.mycode.a;
import sscce.mycode.b.RestrictedObject;
import sscce.usercode.SomeUserClass;
public class SomeClass {
public static void main(String[] args) {
SomeUserClass userClass=new SomeUserClass();
// If I can create it from here, anyone can...
RestrictedObject object=new RestrictedObject();
userClass.someMethod(object);
}
}
sscce.mycode.b.Interface.java:
package sscce.mycode.b;
public interface Interface {
public void someMethod(RestrictedObject restrictedObject);
}
sscce.mycode.b.RestrictedObject.java:
package sscce.mycode.b;
public class RestrictedObject {
public RestrictedObject() {}
}
sscce.usercode.SomeUserClass.java:
package sscce.usercode;
import sscce.mycode.b.Interface;
import sscce.mycode.b.RestrictedObject;
public class SomeUserClass implements Interface {
#Override
public void someMethod(RestrictedObject restrictedObject) {
// It receives an instance, but cannot create it.
System.out.println("Got "+restrictedObject);
}
}
Motivation: Having everything in one package sounds messy...
Does anyone have ideas on how to accomplish this without flattening the packages?
Thanks in advance for any solutions, ideas or comments, Till
You could do it the following way, however you should carefully consider if you really want to use this approach as it is very slow and quite frankly, bad practice.
I'll put it up anyway as to how you can do it:
public final class Secured {
private static final Set<Class<?>> allowedCallers = new HashSet<>();
static {
allowedCallers.add(Allowed.class);
}
private static final class SecurityManagerExtension extends SecurityManager {
private static final int OFFSET = 4;
#Override
protected Class<?>[] getClassContext() {
return super.getClassContext();
}
private Class<?> getCaller() {
try {
return getClassContext()[OFFSET];
} catch (ArrayIndexOutOfBoundsException e) {
return null;
}
}
}
private Secured() {
// protect against reflection attack
Class<?> caller = new SecurityManagerExtension().getCaller();
if (!this.getClass().equals(caller)) {
throw new IllegalStateException();
}
System.out.println("Secured instance constructed!");
}
public static Secured createInstance() {
// this gets the class name of the calling class
Class<?> caller = new SecurityManagerExtension().getCaller();
if (allowedCallers.contains(caller)) {
System.out.println("Created instance by '" + caller + "'!");
return new Secured();
} else {
System.out.println("No instance created because call was made by '" + caller + "'!");
return null;
}
}
}
Note the final keyword on the class to prevent subclassing. If you need to subclass the class yourself, move the final keyword to the factory method.
Also note that this is not protected against serialization attacks.