In the program I am making, I am trying to get a formatted season name for a given season(formatted so it . I keep the formatted names in an interface, since if I were to use a map, it would be unnecessarily regenerated, since I don't make an instance of TeamBuilder
The Seasons interface:
public interface Seasons {
/*
* Contains a formatted list of seasons.
*
* An interface is being used as an alternative to using a Map in the
* TeamBuilder class, since calling parseTeam would have to build
* mappings for the seasons each time it
* was called. This way, the formatted name can simply be grabbed
*/
final String Skyrise = "Skyrise";
final String Toss_Up = "Toss%20Up";
final String Sack_Attack = "Sack%20Attack";
final String GateWay = "Gateway";
final String Round_Up = "Round%20Up";
final String Clean_Sweep = "Clean%20Sweep";
final String Elevation = "Elevation";
final String Bridge_Battle = "Bridge%20Battle";
final String Nothing_But_Net = "Nothing%20But%20Net";
final String Starstruck = "Starstruck";
final String In_The_Zone = "In%20The%20Zone";
final String Turning_Point = "Turning%20Point";
}
The problem comes when I try to grab these seasons. My TeamBuilder class takes in an argument(String season), which is unformatted. My question is, is there any way that I can use a String argument for a method to get a specific item from an interface? This is the most preferable to using a HashMap, which would needlessly regenerate the same information
All these classes can be found on the Github page for this project.
If you want to do it in a typed way, you can use Enum for this:
enum Season{
Skyrise,Toss_Up, Sack_Attack;
#Override
public String toString() {
switch(this){
case Skyrise: return "Skyrise";
case Toss_Up: return "Toss%20Up";
case Sack_Attack: return "Sack_Attack";
default: return "";
}
}
}
public class main{
public static void printSeason(Seasons seasons){
System.out.println(seasons);
}
public static void main(String[] args) {
Seasons e = Seasons.Skyrise;
printSeason(e);
System.out.println(e);
}
}
Since the compiler internally invokes the toString(), you can pass the argument as a Seasons or a String like my example.
And if you still want to use a map without "unnecessarily regenerated" you can use a static field with static initializer like this:
class Seasons {
private static Map<String,String> map = new HashMap<>();
static {
map.put("Skyrise", "Skyrise");
map.put("Toss_Up", "Toss%20Up");
}
public static String getFormatted(String key){
return map.getOrDefault(key,"");
}
}
class main{
public static void main(String[] args) {
System.out.println(Seasons.getFormatted("Skyrise"));
}
}
Just to integrate on Snoob answer you can have enum with fields, so:
enum Season
{
Skyrise("Skyrise"),
Toss_Up("Toss%20Up"),
Sack_Attack("Sack%20Attack")
;
public final String fancyName;
private Season(String fancyName)
{
this.fancyName = fancyName;
}
}
You really have all the benefits without any drawback.
Related
public static class One {
#Override
public String interact(String... values) {
String actualTextOne = "test";
return actualTextOne;
}
}
public static class Two {
#Override
public String interact(String... values) {
String actualTextTwo = "test";
/* Here I need to compare actualTextOne and actualTextTwo, but the problem is that I can't find solluction how to use actualTextOne in Two class*/
return actualTextTwo;
}
}
You cannot do that.
Please check variable scope in java.
https://www.codecademy.com/articles/variable-scope-in-java
A possible solution here is to call the method interact from the class One. Something like this
public static class Two {
#Override
public String interact(String... values) {
String actualTextTwo = "test";
One one = new One();
String actualTextOne = one.interact(values);
// compare values here
return actualTextTwo;
}
}
Why in your classes functions have parameters if you dont use it?
You can mark your class with static only if he is nested, else you need do like this:
class Two {
static public String interact(String... values) {
String actualTextTwo = "test";
return actualTextTwo;
}
}
String textOne = One.interact("");
String textTwo = Two.interact("");
System.out.println(textOne==textTwo);
Java prohibits access of a final static field from an initializer. For example:
public enum Example {
ValueA("valueAA", "valueAB"),
ValueB("valueBA", "valueBB");
final static Map<String, Example> exampleByPropertyA = new HashMap<>();
final String propertyA;
final String propertyB;
Example(String propertyA, String propertyB) {
this.propertyA = propertyA;
this.propertyB = propertyB;
Example.exampleByPropertyA.put(propertyA, this); // <- Not permitted
}
}
However, if the update to the static Map is performed in a separate method that is called by the initializer, this is fine. For example:
public enum Example {
ValueA("valueAA", "valueAB"),
ValueB("valueBA", "valueBB");
final static Map<String, Example> exampleByPropertyA = new HashMap<>();
final String propertyA;
final String propertyB;
Example(String propertyA, String propertyB) {
this.propertyA = propertyA;
this.propertyB = propertyB;
addExample(this);
}
private addExample(Example example) {
Example.exampleByPropertyA.put(example.propertyA, example); // <- Permitted
}
}
Given this context, my question is: Does a call to a member method constitute a "freeze action" or is it indicative to the JVM that the object is, for all intents and purposes, "initialized"? Curious why this makes a difference.
I've done some searching, but haven't found anything that articulates this well.
Thank you in advance!
Does a call to a member method constitute a "freeze action" or is it indicative to the JVM that the object is, for all intents and purposes, "initialized"? Curious why this makes a difference.
The problem is that your class is initialised top to bottom. This means your static fields have not been initialised yet i.e. your Map is null.
Another approach is to add a static initialisation block to be called after everything has been initialised.
static {
for (Example e: values()) {
addExample(e);
}
}
private static addExample(Example example) {
Example prev = exampleByPropertyA.put(example.propertyA, example);
assert prev == null;
}
NOTE: You can see a final variable before it is initialised. This means final can have a before and after value even without using reflection.
public class A {
final String text = getText();
private String getText() {
System.out.println("text= " + text);
return "is set";
}
public static void main(String... args) {
new A().getText();
}
}
prints
text= null
text= is set
Using reflection you can alter final fields even after initialisation though you should avoid doing this unless there is no other option.
The correct way to do what you're trying to do, is to write a static initializer, which runs after all the enums have been created.
Defensive programming: You should also add a simple check to guard against programming errors.
public enum Example {
ValueA("valueAA", "valueAB"),
ValueB("valueBA", "valueBB");
final static Map<String, Example> exampleByPropertyA = new HashMap<>();
static {
for (Example ex : values())
if (exampleByPropertyA.put(ex.propertyA, ex) != null)
throw new IllegalStateException("Duplicate propertyA: " + ex.propertyA);
}
final String propertyA;
final String propertyB;
Example(String propertyA, String propertyB) {
this.propertyA = propertyA;
this.propertyB = propertyB;
}
}
I'm really new to Java and programming in general (~3 weeks of experience) so sorry if this question is obvious for you guys. I tried searching for answers here but couldn't find any that fit my specific problem. And yeah it's for school, I'm not trying to hide it.
Here I'm supposed to write an object method that returns the string contained in the object oj, in reverse. I do know how to print a string in reverse, but I don't know how I should call the object since the method isn't supposed to have any parameters.
import java.util.Random;
public class Oma{
public static void main(String[] args){
final Random r = new Random();
final String[] v = "sininen punainen keltainen musta harmaa valkoinen purppura oranssi ruskea".split(" ");
final String[] e = "etana koira kissa possu sika marsu mursu hamsteri koala kenguru papukaija".split(" ");
OmaMerkkijono oj = new OmaMerkkijono(v[r.nextInt(v.length)] + " " + e[r.nextInt(e.length)]);
String reve = oj.printreverse();
System.out.println(reve);
}
}
class OmaMerkkijono{
private String jono;
public OmaMerkkijono(String jono){
this.jono=jono;
}
public String printreverse(){
//so here is my problem, i tried calling the object in different ways
//but none of them worked
return reversedstringthatdoesnotexist;
}
}
You just need to add this to your "printreverse" method :
new StringBuilder(this.jono).reverse().toString()
With this, when you call the method with the object "oj":
String reve = oj.printreverse();
After the previous line, "reve" must contain the value of the String reversed.
Olet hyvä, moi moi!
To revers a String use StringBuilder and reverse()
public String printreverse(){
return new StringBuilder(jono).reverse().toString();
}
To access private attributes from outside the class you use what are called accessors and mutators, aka getters and setters.
You just need a basic getter that also reverses the string.
public class MyObject {
private String objectName;
MyObject(String objectName) {
this.objectName = objectName;
}
public String getObjectName() {
return objectName; // returns objectName in order
}
public String getReversedObjectName() {
return new StringBuilder(objectName).reverse().toString();
}
public static void main(String[] args) {
MyObject teslaRoadster = new MyObject("Telsa Roadster");
System.out.println(teslaRoadster.getObjectName());
System.out.println(teslaRoadster.getReversedObjectName());
}
}
Output:
Telsa Roadster
retsdaoR asleT
I'm writing a library, which has a predefined set of values for an enum.
Let say, my enum looks as below.
public enum EnumClass {
FIRST("first"),
SECOND("second"),
THIRD("third");
private String httpMethodType;
}
Now the client, who is using this library may need to add few more values. Let say, the client needs to add CUSTOM_FIRST and CUSTOM_SECOND. This is not overwriting any existing values, but makes the enum having 5 values.
After this, I should be able to use something like <? extends EnumClass> to have 5 constant possibilities.
What would be the best approach to achieve this?
You cannot have an enum extend another enum, and you cannot "add" values to an existing enum through inheritance.
However, enums can implement interfaces.
What I would do is have the original enum implement a marker interface (i.e. no method declarations), then your client could create their own enum implementing the same interface.
Then your enum values would be referred to by their common interface.
In order to strenghten the requirements, you could have your interface declare relevant methods, e.g. in your case, something in the lines of public String getHTTPMethodType();.
That would force implementing enums to provide an implementation for that method.
This setting coupled with adequate API documentation should help adding functionality in a relatively controlled way.
Self-contained example (don't mind the lazy names here)
package test;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<HTTPMethodConvertible> blah = new ArrayList<>();
blah.add(LibraryEnum.FIRST);
blah.add(ClientEnum.BLABLABLA);
for (HTTPMethodConvertible element: blah) {
System.out.println(element.getHTTPMethodType());
}
}
static interface HTTPMethodConvertible {
public String getHTTPMethodType();
}
static enum LibraryEnum implements HTTPMethodConvertible {
FIRST("first"),
SECOND("second"),
THIRD("third");
String httpMethodType;
LibraryEnum(String s) {
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
static enum ClientEnum implements HTTPMethodConvertible {
FOO("GET"),BAR("PUT"),BLAH("OPTIONS"),MEH("DELETE"),BLABLABLA("POST");
String httpMethodType;
ClientEnum(String s){
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
}
Output
first
POST
Enums are not extensible. To solve your problem simply
turn the enum in a class
create constants for the predefined types
if you want a replacement for Enum.valueOf: track all instances of the class in a static map
For example:
public class MyType {
private static final HashMap<String,MyType> map = new HashMap<>();
private String name;
private String httpMethodType;
// replacement for Enum.valueOf
public static MyType valueOf(String name) {
return map.get(name);
}
public MyType(String name, String httpMethodType) {
this.name = name;
this.httpMethodType = httpMethodType;
map.put(name, this);
}
// accessors
public String name() { return name; }
public String httpMethodType() { return httpMethodType; }
// predefined constants
public static final MyType FIRST = new MyType("FIRST", "first");
public static final MyType SECOND = new MyType("SECOND", "second");
...
}
Think about Enum like a final class with static final instances of itself. Of course you cannot extend final class, but you can use non-final class with static final instances in your library. You can see example of this kind of definition in JDK. Class java.util.logging.Level can be extended with class containing additional set of logging levels.
If you accept this way of implementation, your library code example can be like:
public class EnumClass {
public static final EnumClass FIRST = new EnumClass("first");
public static final EnumClass SECOND = new EnumClass("second");
public static final EnumClass THIRD = new EnumClass("third");
private String httpMethodType;
protected EnumClass(String name){
this.httpMethodType = name;
}
}
Client application can extend list of static members with inheritance:
public final class ClientEnum extends EnumClass{
public static final ClientEnum CUSTOM_FIRST = new ClientEnum("custom_first");
public static final ClientEnum CUSTOM_SECOND = new ClientEnum("custom_second");
private ClientEnum(String name){
super(name);
}
}
I think that this solution is close to what you have asked, because all static instances are visible from client class, and all of them will satisfy your generic wildcard.
We Fixed enum inheritance issue this way, hope it helps
Our App has few classes and each has few child views(nested views), in order to be able to navigate between childViews and save the currentChildview we saved them as enum inside each Class.
but we had to copy paste, some common functionality like next, previous and etc inside each enum.
To avoid that we needed a BaseEnum, we used interface as our base enum:
public interface IBaseEnum {
IBaseEnum[] getList();
int getIndex();
class Utils{
public IBaseEnum next(IBaseEnum enumItem, boolean isCycling){
int index = enumItem.getIndex();
IBaseEnum[] list = enumItem.getList();
if (index + 1 < list.length) {
return list[index + 1];
} else if(isCycling)
return list[0];
else
return null;
}
public IBaseEnum previous(IBaseEnum enumItem, boolean isCycling) {
int index = enumItem.getIndex();
IBaseEnum[] list = enumItem.getList();
IBaseEnum previous;
if (index - 1 >= 0) {
previous = list[index - 1];
}
else {
if (isCycling)
previous = list[list.length - 1];
else
previous = null;
}
return previous;
}
}
}
and this is how we used it
enum ColorEnum implements IBaseEnum {
RED,
YELLOW,
BLUE;
#Override
public IBaseEnum[] getList() {
return values();
}
#Override
public int getIndex() {
return ordinal();
}
public ColorEnum getNext(){
return (ColorEnum) new Utils().next(this,false);
}
public ColorEnum getPrevious(){
return (ColorEnum) new Utils().previous(this,false);
}
}
you could add getNext /getPrevious to the interface too
#wero's answer is very good but has some problems:
the new MyType("FIRST", "first"); will be called before map = new HashMap<>();. in other words, the map will be null when map.add() is called. unfortunately, the occurring error will be NoClassDefFound and it doesn't help to find the problem. check this:
public class Subject {
// predefined constants
public static final Subject FIRST;
public static final Subject SECOND;
private static final HashMap<String, Subject> map;
static {
map = new HashMap<>();
FIRST = new Subject("FIRST");
SECOND = new Subject("SECOND");
}
private final String name;
public Subject(String name) {
this.name = name;
map.put(name, this);
}
// replacement for Enum.valueOf
public static Subject valueOf(String name) {
return map.get(name);
}
// accessors
public String name() {
return name;
}
I am experimenting here a bit.
Say I have a class :
static class MyClass {
static String property = "myProperty";
}
and a method:
public static void myMethod0(Class<MyClass> clazz) {
try {
MyClass myClass = clazz.newInstance();
System.out.println (myClass.property);
} catch (Exception e) {
e.printStackTrace();
}
}
and to test it:
public static void main(String[] args ) {
myMethod0(MyClass.class);
}
myMethod0 would work here, however, I am creating a new instance in order to reach the property.
Since the properties are static I should be able to reach them without actually creating any instance. For example as you would do when reaching a static property, ie MyClass.property
To summarize:
Is it possible to reach the static property of MyClass, by having Class clazz = MyClass.class ?
Thanks !
**
EDIT:
**
To put the above in perspective and what I am actually trying to accomplish:
public static class PDF_1 { public static PDF_1 it = new PDF_1();
static String contentType = "application/pdf";
static String fileEnding = "pdf";
}
static void myMethod0(PDF_1 pdf) {
System.out.println(pdf.fileEnding);
}
public enum PDF_2 {it;
static String contentType = "application/pdf";
static String fileEnding = "pdf";
}
static void myMethod1(PDF_2 pdf) {
System.out.println(pdf.fileEnding);
}
public static void main(String[] args ) {
myMethod0(PDF_1.it); // Works fine! However very verbose because of public static PDF_1 it = new PDF_1();
myMethod1(PDF_2.it); // Works fine! Somewhat verbose though because of the "it" keyword
}
The whole idea as to what I am trying to accomplish with this, is that too often do I see people declare lots of strings, ie:
static class Constants {
static String PDF_CONTENT_TYPE = "application/pdf";
static String PDF_FILE_ENDING = "pdf";
static String HTML_CONTENT_TYPE = "text/html";
static String HTML_FILE_ENDING = "html";
}
// There is no way knowing what type the method actually wants. Is it contentType, fileEnding or something entirely different ?
public void myMethod(String str) {
}
What I am trying to achieve is something that would allow you to pass a main class/enum, ie: PDF and the method will itself determine what it will use. The caller will just know what to pass, a PDF or HTML class/enum. I am also looking for something that is this refactor friendly as well. It is also of interest not to complicate the declaration of this creation. I find fully blown enums just as obtrusive as a class, and can be hard to read. The ide a is that I am just grouping the two strings in a parent object "PDF" and "HTML". An enum:
public enum SomeType {
PDF("application/pdf", "pdf"), HTML(...);
String contentType;
String fileEnding;
// Constructor ...
}
Would not allow you to declare a method and specify that this method expects the HTML stuff. Only that the enum type is of type SomeType. There is a risk that "someone" would pass SomeType.PDF to that method. What I am doing with the enum and class seems like a noob solution, and the Java language should provide a feature like this, or does it already?
Does this make sense?
You could use reflection
System.out.println(myClass.getDeclaredField("property").get(null));
The get-method usually requires an instance to get the attribute from, but since property is static, you may pass it a null.
I hope you meant this - I wrote tests with hamcrest - so don't wonder ;)
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
import org.junit.Test;
public class TestEnumEnding {
#Test
public void whenMethod1WithFiletypeHtmlWeShouldGetStringText_Html() throws Exception {
// Arrange
String contentType = null;
// Act
contentType = method1(Filetype.HTML);
// Assert
assertThat(contentType, is("text/html"));
}
#Test
public void whenMethod1WithFiletypePdfWeShouldGetapplication_pdf() throws Exception {
// Arrange
String contentType = null;
// Act
contentType = method1(Filetype.PDF);
// Assert
assertThat(contentType, is("application/pdf"));
}
private static String method1 (Filetype anyFiletype) {
return anyFiletype.getContentType();
}
public enum Filetype {
HTML("html","text/html"), PDF("pdf","application/pdf");
private final String fileEnding;
private final String contentType;
private Filetype(String fileEnding, String contentType) {
this.fileEnding = fileEnding;
this.contentType = contentType;
}
public String getFileEnding() {
return this.fileEnding;
}
public String getContentType() {
return this.contentType;
}
}
}
public enum PDF { it;
static String contentType = "application/pdf";
static String fileEnding = "pdf";
}
static void myMethod1(PDF pdf) {
System.out.println(pdf.fileEnding);
}
public static void main(String[] args ) {
myMethod1(PDF.it); // Works fine! Somewhat verbose though because of the "it" keyword. Not 100% ideal!
}