Inside public class we want switchcase based on package name in every case we are calling one public URL.. i tried this way it is not working switch case
public class AllChanges {
Context context;
Switch(getPackageName()) {
case "com.agilerise.package1":
public static String gurl = "http://google.com/index.php";
break;
case "com.agilerise.package2":
public static String gurl = "http://bing.com/index.php";
case "com.agilerise.package2":
public static String gurl = "http://stackoverlfow.com/index.php";
break;
}
}
public class AllChanges {
public static String gurl ="";
public void seturl()
{
Switch(getPackageName()) {
case "com.agilerise.package1":
gurl = "http://google.com/index.php";
break;
case "com.agilerise.package2":
gurl = "http://bing.com/index.php";
break;
case "com.agilerise.package2":
gurl = "http://stackoverlfow.com/index.php";
break;
}
}
}
call like this
AllChanges allchanges=new AllChanges();
allchanges.seturl();
The better way is to use polymorphism here:
Instead of examining the classes package (which may vary and result in duplicated entries for subclasses) you should define an interface:
interface SearchEngineSelector{
URL getSearchEngineUrl();
}
Then You have specialized sub interfaces with default methods:
interface GoogleSearchEngineSelector extends SearchEngineSelector{
URL THE_URL = new URL("http://google.com/index.php");
default public URL getSearchEngineUrl(){
return THE_URL;
}
Your classes then can implement one of the specialized sub interfaces :
class SomeClass implements GoogleSearchEngineSelector {
// ...
}
and your code code change to: Nothing
because there is nothing to do for a subclass...
Java doesn't work that way. You can write statements only inside functions in Java. And declarations of variables can come in class outside of functions.
I would suggest you to read about scope.
https://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.3
You need to declare your variables in the class scope. And your switch case has to be within a function. Your example has a duplicated case, you should probably fix that. com.agilerise.package1, com.agilerise.package2, com.agilerise.package3
public class AllChanges {
public static String gurl = "";
Context context;
private void myFunction(){
switch(getPackageName()) {
case "com.agilerise.package1":
gurl = "http://google.com/index.php";
break;
case "com.agilerise.package2":
gurl = "http://bing.com/index.php";
break;
case "com.agilerise.package3":
gurl = "http://stackoverlfow.com/index.php";
break;
}
}
}
This is a more elegant solution. You should try to avoid static variables. You could then call this function by String url = getUrl(myFunction());
private String getUrl(String s){
switch(s) {
case "com.agilerise.package1":
return "http://google.com/index.php";
case "com.agilerise.package2":
return "http://bing.com/index.php";
case "com.agilerise.package3":
return "http://stackoverlfow.com/index.php";
default:
return "SomeDefaultUrl";
}
}
Related
I have a class called "ClientFontRenderer" and I want to know the best way to store this. The method is being called every frame update which can be extremely quick so I'm not sure if I'm able to use arrays. What is the best way to store these variables in such a way that I can load them without a problem?
public class FontManager {
public static final FontManager INSTANCE;
private ClientFontRenderer LATOREGULAR, LATOSMALL, LATOBOLD;
private ClientFontRenderer SANSREGULAR, SANSBOLD, SANSITALIC;
public FontManager() {
}
public void initialize() {
LATOREGULAR = new ClientFontRenderer("Lato-Light", 16.0F);
LATOSMALL = new ClientFontRenderer("Lato-Light", 11.0F);
LATOBOLD = new ClientFontRenderer("Lato-Bold", 16.0F);
SANSREGULAR = new ClientFontRenderer("Sans-Regular", 16.0F);
}
public ClientFontRenderer loadFont(FontType type) {
switch(type) {
case LATO_REGULAR:
return LATOREGULAR;
case LATO_SMALL:
return LATOSMALL;
case LATO_BOLD:
return LATOBOLD;
case SANS_REGULAR:
return SANSREGULAR;
case SANS_BOLD:
return SANSBOLD;
case SANS_ITALIC:
return SANSITALIC;
default:
return LATOREGULAR;
}
}
static {
INSTANCE = new FontManager();
}
public enum FontType {
LATO_REGULAR,
LATO_SMALL,
LATO_BOLD,
SANS_REGULAR,
SANS_BOLD,
SANS_ITALIC
}
imo since you only used static initializers, you can make loadFont static as well
public class FontManager {
private static final EnumMap<FontType, ClientFontRenderer> fontMap = new EnumMap<>(FontType.class);
static {
fontMap.put(FontType.LATO_REGULAR, new ClientFontRenderer("Lato-Light", 16.0F);
...
}
public static ClientFontRenderer loadFont(FontType type) {
return fontMap.get(type);
}
public enum FontType {
LATO_REGULAR,
LATO_SMALL,
LATO_BOLD,
SANS_REGULAR,
SANS_BOLD,
SANS_ITALIC
}
)
i have an enum like below:
public enum TripType {
TRIP1,
TRIP2,
TRIP3,
TRIP4
}
Then i have a method which receives a string parameter setupTravel(String tripType) and i need to check the value of tripType with a TripType. I wish to use a switch-case as below:
setupTravel(String tripType){
switch (tripType){
case TripType.TRIP1.toString():
setup1();
break;
case TripType.TRIP2.toString():
setup2();
break;
}
}
But, in the line TripType.TRIP1.toString() it complains with:
Constant expression required
How can i fix it?
setupTravel(String tripType) {
try {
switch (TripType.valueOf(tripType)) {
case TRIP1:
setup1();
break;
case TRIP2:
setup2();
break;
}
} catch (IllegalArgumentException ex) {
// Handle invalid trip type here
}
}
Since your method seems to switch on the Enum string, why not just use the Enum? You may want to include a default unless you have all Enums in the switch block.
setupTravel(TripType type){
switch (type){
case TRIP1:
setup1();
break;
case TRIP2:
setup2();
break;
}
}
You would call it as
setupTravel(TripType.TRIP1)
If it will be useful for you, You can use an enum constructor instead of using a switch case.
Something like this:
public enum TripType {
TRIP1("setup1"), TRIP2("setup2");
String setup;
private TripType(String setup) {
this.setup = setup;
}
public String getSetup() {
return setup;
}
public static TripType getTripTypeByName(String name) {
return Arrays.stream(TripType.values()).filter(t -> t.name().equalsIgnoreCase(name)).findAny().orElse(null);
}
}
And getting enum based on the name, you can use like this:
TripType tripType = TripType.getTripTypeByName("trip1");
System.out.println(tripType != null ? tripType.getSetup() : null);
Depending on an Input given in another class, this class has to retrieve a variable from one of 4 classes in which that variable is to be found. Eg. if the input has been an s the variable this class is looking for is found in Sumup.counter whereas when the input has been an a the variable it needs, is to be found in Abstract.counter etc etc, in order to fill an Array. In one of these 4 different classes it has to pick up 5 different variables. So in order to avoid lots of extra programming I want to replace these class names Sumup and Abstract with a variable. So it has to look like anything like this Variable.counter, Variable.part1 etc. In which Variable can be either Sumup or Abstract (or Multiply or Divide).
Anyone a suggestion how to do this?
public class Erroranalysis {
public static int[][] wrongcalculations = new int[5][Numberofcalculations.numcalc];
static int runner = 0;
static String routine;
public static void main(String[] args)
{
switch (kindofcalculation.choice)
{
case "s":
routine = "Sumup";
break;
case "a":
routine = "Abstract";
break;
case "m":
routine = "Multiply";
break;
case "d":
routine = "Divide";
break;
}
if (routine.counter <= Numberofcalcluations.numcalc)
{
wrongcalculations[0][runner] = routine.counter;
wrongcalculations[1][runner] = routine.part1;
wrongcalculations[2][runner] = routine.part2;
wrongcalculations[3][runner] = routine.result;
wrongcalculations[4][runner] = routine.answer;
runner++;
}
}
}
you can opt for a base abstract class and make an array of that class:
class Base{
public int counter = 0;
}
class Sumup extends Base{
}
class Abstract extends Base{
}
public class Erroranalysis {
public static int[][] wrongcalculations = new int[5][Numberofcalculations.numcalc];
static int runner = 0;
static Base routine;
static Sumup sumup;
static Abstract abs;
public static void main(String[] args)
{
sumup = new Sumup();
abs = new Abstract();
// possibly, this part won't be in main, but in some for loop of another method
switch (kindofcalculation.choice)
{
case "s":
routine = sumup;
case "a":
routine = abs;
}
if (routine.counter <= Numberofcalcluations.numcalc)
{
wrongcalculations[0][runner] = routine.counter;
wrongcalculations[1][runner] = routine.part1;
wrongcalculations[2][runner] = routine.part2;
wrongcalculations[3][runner] = routine.result;
wrongcalculations[4][runner] = routine.answer;
runner++;
}
}
}
If I´m using an enum to determine the type of a task.
public enum TaskType {
TYPE_ONE("Type1"),TYPE_TWO("Type2"),TYPE_THREE("Type3");
private final String type;
private StageType(String type) {
this.type = type;
}
#Override
public String toString() {
return type;
}
}
how can I assure at one point in my Application
if(taskType == TaskType.TYPE_ONE) {
typeOneProcessing();
} else if(taskType == TaskType.TYPE_TWO) {
typeTwoProcessing();
} else if(taskType == TaskType.TYPE_THREE) {
typeThreeProcessing();
}
that every enum value is used?
I mean if I need to add a new TYPE_FOUR someday, I´d need to find every place in my code where I used the enum, so I ask myself if there is a better way so that I either avoid the enum and use some other concept or that I can ensure that every value of the enum is used in that piece of code.
There are findbugs type tools for doing that but you could consider removing the if-then-else completely and put the processing inside the enum. Here, adding a new TYPE_FOUR will force you to write it's doProcessing() method.
public interface DoesProcessing {
public void doProcessing();
}
public enum TaskType implements DoesProcessing {
TYPE_ONE("Type1") {
#Override
public void doProcessing() {
}
},
TYPE_TWO("Type2") {
#Override
public void doProcessing() {
}
},
TYPE_THREE("Type3") {
#Override
public void doProcessing() {
}
},
TYPE_FOUR("Type4") {
// error: <anonymous com.oldcurmudgeon.test.Test$TaskType$4> is not abstract and does not override abstract method doProcessing() in DoesProcessing
};
private final String type;
private TaskType(String type) {
this.type = type;
}
#Override
public String toString() {
return type;
}
}
public void test() {
DoesProcessing type = TaskType.TYPE_TWO;
type.doProcessing();
}
If you would prefer an abstract method then this works:
public enum TaskType {
TYPE_ONE("Type1") {
#Override
public void doProcessing() {
}
},
TYPE_TWO("Type2") {
#Override
public void doProcessing() {
}
},
TYPE_THREE("Type3") {
#Override
public void doProcessing() {
}
};
private final String type;
private TaskType(String type) {
this.type = type;
}
// Force them all to implement doProcessing.
public abstract void doProcessing();
#Override
public String toString() {
return type;
}
}
You could put the process method as an abstract method in TaskType, and then override it in every task in the enum. What would probably be a better idea is if you create an interface, something like:
public interface Task {
void process();
}
Then you either let your enum implement this interface. Or, probably better, you create concrete classes implementing this interface. One class for each of your task types.
I think you are saying that you are wanting the compiler to tell you that all of the enum's values are considered.
Unfortunately, Java doesn't support that.
You might think that you could write something like this:
public int method(TaskType t) {
switch (t) {
case TYPE_ONE: return 1;
case TYPE_TWO: return 2;
case TYPE_THREE: return 3;
}
// not reachable ... no return required
}
... and rely on the compiler to tell you if you left out one of the enum values in the switch cases.
Unfortunately, it doesn't work!! The above is a compilation error anyway. According to the JLS reachability rules, the switch statement needs a default: arm for that method to be valid. (Or you can add a return at the end ...)
There is a good reason for this oddity. The JLS binary compatibility rules say that adding a new value to an enum is a binary compatible change. That means that any code with switch statement that switches on an enum needs to still remain valid (executable) code after the addition of enum values. If method was valid to start with, it can't become invalid (because there is a return path with no return statement) after the binary compatible change.
In fact, this is how I would write the code above:
public int method(TaskType t) {
switch (t) {
case TYPE_ONE: return 1;
case TYPE_TWO: return 2;
case TYPE_THREE: return 3;
default:
throw new AssertionError("TaskType " + t + " not implemented");
}
// not reachable ... no return required
}
This doesn't pretend to be compile-time safe, but it is fail-fast, and it doesn't involve bad OO design.
AFAIK you can't do it "automatically".
To minimize the risk of forgetting to add an if/case for new value you could have one "service" class for each enum value and a factory which provides a specific service for enum value.
E.g. instead of:
void methodA(TaskType type) {
doSth();
switch(type) {
case TYPE_ONE:
foo1();
break;
case TYPE_TWO:
foo2();
break;
...
}
}
void methodB(TaskType type) {
doSthElse();
switch(type) {
case TYPE_ONE:
bar1();
break;
case TYPE_TWO:
bar2();
break;
...
}
}
do:
interface Service {
foo();
bar();
}
class ServiceFactory {
Service getInstance(TaskType type) {
switch(type) {
case TYPE_ONE:
return new TypeOneService();
case TYPE_TWO:
return new TypeTwoService();
default:
throw new IllegalArgumentException("Unsupported TaskType: " + type);
}
}
}
And then the methods above can be rewritten as follows:
void methodX(TaskType type) {
doSth();
ServiceFactory.getInstance(type).foo();
}
This way you have only one point where you have to add handling of new enum value.
HashMap<String, Integer> hm=new HashMap<String, Integer>();
...
if(taskType == TaskType.TYPE_ONE) {
typeOneProcessing();
hm.put(TaskType.TYPE_ONE, 1)
} else if(taskType == TaskType.TYPE_TWO) {
typeTwoProcessing();
hm.put(TaskType.TYPE_TWO, 1)
} else if(taskType == TaskType.TYPE_THREE) {
typeThreeProcessing();
hm.put(TaskType.TYPE_THREE, 1)
}
...
for (TaskType t : TaskType.values()) {
if(hm.get(t)!=1)
// Trigger the alarm
}
You can even count the times the element was count if you need it
You can do swich case on the enum, and fail if the default is hit:
switch(taskType ){
case TYPE_ONE: ... break;
case TYPE_TWO: ... break;
case TYPE_THREE: ... break;
default:
throw new IllegalStateException("Unsupported task type:"+taskType);
}
I have an interface and these methods:
public interface Form {
public void setFirstName (String value);
public void setLastName (String value);
public void setGender (String value);
}
Can I call these methods randomly on an objet? Something like:
form.randomMethodFromFormInterface(String randomString);
Is it actually possible? Just to clarify, I would like to fillout the form randomly: sometimes just the last name, sometimes just the first name, sometimes just the gender.
Random rand = new Random();
switch (rand.nextInt(3)) {
case 0: myForm.setFirstName(myFirstName); break;
case 1: myForm.setLastName(myLastName); break;
case 2: myForm.setGender(myGender); break;
default: throw new IllegalStateException();
}
Couldn't you use Random to pick from 0-2, and then depending on that value call the corresponding method?
Could you make another method in the interface that generates a random number and calls a method based on that number? Although I would bet there's an easier way to do this than creating an interface for it.
Here a general way, using reflection:
private static Random r = new Random();
public static void callRandomMethod(Object target, Class<?> iface, Object ... arguments) {
List<Method> methods = findFittingMethods(iface, arguments);
Method m = methods.get(r.nextInt(methods.size()));
m.invoke(target, arguments);
}
public List<Method> findFittingMethods(Class<?> iface, Object ... arguments
Method[] allMethods = iface.getMethods();
List<Method> fittingMethods = new ArrayList<Method>();
findMethodLoop:
for(Method candidate : allMethods) {
Class<?>[] argumentTypes = candidate.getArguments();
if(argumentTypes.length != arguments.length) {
continue;
}
// check argument types
for(int i = 0; i < argumentTypes.length; i++) {
if(arguments[i] == null) {
if(argumentTypes[i].isPrimitive()) {
// null can't be passed to a primitive argument.
continue findMethodLoop;
}
else {
// ... but to every other argument type.
continue; // check next argument
}
}
if(argumentTypes[i].isInstance(arguments[i])) {
continue; // check next argument
}
if(argumentTypes[i].isPrimitive()) {
// hack to check if we have the right wrapper class
try {
Array.set(Array.newInstance(argumentTypes[i], 1), 0, arguments[i]);
continue; // check next argument
}
catch(ArrayStoreException ex) {
continue findMethodLoop;
}
}
// wrong type
continue findMethodLoop;
}
// now we found a method which would accept the arguments, put it into the list.
fittingMethods.add(candidate);
}
return fittingMethods;
}
Of course, if you do this often, you would not create the list of methods for every call, but only once, and reuse it then. (And if you only have a known interface with a low number of methods, use the switch statement instead, like others have recommended.)
You can place the various method names in an array structure.
Then choose a random index within the scope of the array.
Then use reflection to actually call the method using the randomly chosen name from the previous step
Why not make the following method:
public static void randomMethodFromFormInterface(Form form, String value) {
switch(random.nextInt(3) {
case 0:
form.setFirstName(value);
break;
case 1:
form.setLastName(value);
break;
case 2:
form.setGenderName(value);
break;
}
}
You can put it in a utility class. random here is, of course, an instance of java.util.Random.
Can I call these methods randomly on
an objet?
Yes, this is possible with Reflection. The randomness is not implemented in this example (I assume that you can easily do this with a random int) and all methods are called without knowing how they are named or how many methods are available. For simplicity the example assumes that the parameter is only a String (like in your example). Of course, you must instantiate a class which implements Form:
Class thisClass = Class.forName("FormImpl");
Object o = thisClass.newInstance();
Method[] methods = thisClass.getDeclaredMethods();
for(Method m : methods)
{
m.invoke(o, "test");
}
You could do something like below. However, I am not sure if I really like the idea of calling methods in an interface randomly. It breaks the contract in a way and sounds like a bad design idea in my opinion.
import java.util.Random;
public class RandomInterfaceImpl implements RandomInterface {
private Random rnd;
public RandomInterfaceImpl(){
rnd = new Random();
}
#Override
public void setFirstName(String value) {
System.out.println("called setFirstName");
}
#Override
public void setLastName(String value) {
System.out.println("called setLastName");
}
#Override
public void setGender(String value) {
System.out.println("called setGender");
}
#Override
public void getNextRandomMethod(String value) {
int nextRand = rnd.nextInt(3);
switch(nextRand){
case 0: setFirstName(value); break;
case 1: setLastName(value); break;
case 2: setGender(value); break;
}
}
}
public static void main(String[] args) {
RandomInterface myInterface = new RandomInterfaceImpl();
myInterface.getNextRandomMethod("Foo");
myInterface.getNextRandomMethod("Foo");
myInterface.getNextRandomMethod("Foo");
}
prints:-
called setFirstName
called setLastName
called setLastName