I would like to know if i can get this to work:
public enum Items {
Weapon starterBow = new Weapon("Starter Bow", AttackSpeed.SLOW),
Weapon advancedBow = new Weapon("Advanced Bow", AttackSpeed.MEDIUM),
Weapon goldenBow = new Weapon("Golden Bow", AttackSpeed.FAST);
}
I want to access it like this:
Items.starterBow.getName()
(Weapons have a getName() Method)
This code snippet at the beginning is giving me errors, but is there any other way to list Objects like this? (Without creating a new class)
Thanks in advance!
enums syntactically act as regular classes, so you can have fields, methods and constructors.
The difference is that you specifiy the instances of the class during the enum declaration. These instances are created by the jvm and cannot be created in any other way.
This is probably what you are looking for:
public enum Items {
//Fields
String name;
AttackSpeed attackSpeed;
//constructor:
Items(String name, AttackSpeed attkSpd) {
this.name = name;
this.attackSpeed = attkSpd;
}
//methods:
public String getName() {
return name;
}
//listing the instances and calling the constructor:
StarterBow ("Starter Bow", AttackSpeed.SLOW),
AdvancedBow ("Advanced Bow", AttackSpeed.MEDIUM),
GoldenBow ("Golden Bow", AttackSpeed.FAST);
}
Related
I am new to Java. I have a problem to solve, but I don't quite understand how constructors work. I understand how to create a superclass and a subclass but I don't understand the constuctors within them (or how they actually work - I have done rediculous amounts of research on constructors, but it's just not making much sense).
I am trying to write a program that creates a superclass called Employees. This Employee class has instance variables employeeId (which is an integer) and employeeName (which is a String).
The subclass is called Manager. The Manager subclass has an instance variable called employeeTitle (which is a String). It also has a method with the name of managerDetails(). ManagerDetails() is supposed to display the employeeId, employeeName, and the employeeTitle.
This is what I have so far:
package tryingoutjava;
public class TryingOutJava {
class Employee {
int employeeId;
String employeeName;
void Employee() {
}
}
class Manager extends Employee {
String employeeTitle;
void managerDetails() {
}
}
public static void main(String[] args) {
}
}
I am very confused on how to set up the constructors for the superclass and the subclass, or even what a constructor really looks like. I've seen examples all over the internet, but no one actually highlights the actual part that is the constructor, or how everything is linked visually, which is what helps me learn.
I guess I'm also having issues with understanding how to set up a method that calls on an object. If anyone has the time to help, it would greatly be appreciated. Thanks!
I guess you want something like this. Be noted, that it is a good idea to separate classes one-per-file in this case, as they are separate entities here. It is a good idea to limit data access to entity fields, as such using encapsulation.
Employee.java:
package tryingoutjava;
public class Employee {
// Protected access because we want it in Manager
protected int employeeId;
protected String employeeName;
public Employee(int employeeId, String employeeName) {
this.employeeId = employeeId;
this.employeeName = employeeName;
}
}
Manager.java:
package tryingoutjava;
public class Manager extends Employee {
private String employeeTitle;
public Manager(String employeeTitle, int employeeId, String employeeName) {
// Use super to invoke Employee constructor
super(employeeId, employeeName);
this.employeeTitle = employeeTitle;
}
// Just create a simple string describing manager
#Override
public String toString() {
return "Manager{" +
"employeeTitle='" + employeeTitle +
"employeeId=" + employeeId +
", employeeName='" + employeeName + '\'' +
'}';
}
}
Application.java:
package tryingoutjava;
public class Application {
// Example of construction plus printing of Manager data
public static void main(String[] args) {
Employee davie = new Employee(1, "Dave The Cable Guy");
Manager tom = new Manager("CFO", 2, "Tomas");
System.out.println(tom.toString());
}
}
Constructors (most often than not) just delegate construction of parent through super invocation. While there are other techniques, like Builder pattern, this is the most basic and understandable approach. There are several other ways to do this, but this should get you started, hope it helps!
Purpose of Constructor
constructor is a method like other method but it is called when instantiate (or create a object from your class) for initialize your object for first use or later use. for example a class like Student must created (instantiated) when we give it name and family name for example. Without them, create a Student is not good because maybe we forget to give it proper name and use it incorrectly. constructor forces us to provide minimum things needed for instantiating objects from classes.
Constructor implementation in inheritance
About inheritance, it is different. When you want to create a Student which is a Human (extends Human) you must first create Human inside your Student and set special feature for your Student like ID which is not for Human (Human has name and etc). so when you create a Student with constructor, the super constructor (for Human) is called too.
What do we do in constructor
as I mentioned, we provide default value for our properties which must set them before creating and using object. (for using them properly) every subclass call super class constructor implicitly with super() but if super class doesn't have any default constructor (constructor with no argument) you must explicitly say super(...) at the first lien of subclass constructor (otherwise compile error)
What is the program steps when using constructor (Advanced)
super class static constructor and static variable (read by self if you want to know more about things I say here)
subclass class static constructor and static variable
super class variable and block constructor
super class constructors
sub class variable and block constructor
sub class constructors
I only mentioned 4 & 6.
I try to explain completely. My English is not good. I'm sorry.
If you know how a method works, then you know how a constructor works. The constructor is simply a special method that allows you to execute some code before the object is created.
Person p = new Person("Bob", 25); // Calls constructor Person(String name, int age)
Then in the constructor you can do things like assign initial values to any instance variables.
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
If the class is a subclass you need to call a constructor of the parent class before the object is created unless the parent class has a constructor with no parameter in which case java can call it for you if you don't specify anything. Here Worker extends Person.
private String occupation;
public Worker(String name, int age, String occupation) {
super(name, age) // Calls constructor Person(String name, int age)
this.occupation = occupation;
}
I guess you can achieve what you want in a single file via the code snippet below:
You can copy paste it in your code and it should work.
You can see how the constructor of parent class is being called by the help of super() and also the methods. Here I have used methods like getEmployeeTitle() which should help you get an overview on how to write methods. I have also overridden the toString() method so that you can understand how to override Object class' useful methods like toString().
Note : Although I have created all the classes in one code snippet for the sake of simplicity , but it is highly recommended that you create a separate file for each of these classes.
class Employee {
int employeeId;
String employeeName;
Employee(int employeeId, String employeeName) {
this.employeeId = employeeId;
this.employeeName = employeeName;
}
}
class Manager extends Employee {
private String employeeTitle;
Manager(int employeeId, String employeeName, String employeeTitle) {
super(employeeId, employeeName);
this.employeeTitle = employeeTitle;
}
public String getEmployeeTitle() {
return employeeTitle;
}
#Override
public String toString() {
return ("employeeId: " + employeeId + ", employeeName: " + employeeName + ", employeeTitle" + employeeTitle);
}
}
public class TryingOutJava {
public static void main(String[] args) {
Manager manager = new Manager(007, "John Doe", " Sr. Manager");
System.out.println(manager);
System.out.println(manager.getEmployeeTitle());
}
}
The nested builder patterns that I've come across online usually have something like this:
class Person{
private int id;
private String name;
private int age;
... so on
private Person(Builder builder){
this.id = builder.id;
this.name = builder.name;
this.age = builder.age;
}
public static class Builder{
private int id;
private String name;
private int age;
... so on
public Builder id(int id){
this.id = id;
return this;
}
public Builder name(String name){
this.name = name;
return this;
}
.... so on
public Person build(){
return new Person(this);
}
}
}
My question is, is it necessary to duplicate fields in Person and Builder? It seems like a lot of redundant code. And my second question is, would the following code be a viable replacement, why or why not?
class Person{
private int id;
private String name;
private int age;
... so on
private Person(){}
public static class Builder{
private Person person = new Person();
public Builder id(int id){
this.person.id = id;
return this;
}
public Builder name(String name){
this.person.name = name;
return this;
}
.... so on
public Person build(){
return person;
}
// UPDATED -- another build method
public Person build(){
Person built = this.person;
this.person = new Person();
return built;
}
}
}
Note: I understand this topic may be opinionated and there may not be a "right" answer, but I just want to hear different ideas and opinions. I'm not looking for the ultimate truth.
Your code would be fine as long as:
you keep your Person member variables private (you are doing so)
you don't provide methods that allow modification of those member variables (the code you show does not do, but you have omitted parts of it)
those member variables are immutable or you ensure getters provide copies of them. usually better that the members are already immutable (hint: even java collections). otherwise you will be creating instances on each getX call.
once Builder.build is called, noone must be able to modify Person instance state, not even Builder itself. this is not happening in the code you posted
builder does not expose "temporal instance" being built (if any at all). No instance must be exposed aside the return of build method.
there are opinions about which is the preferred way or not, matter of taste most of the time. But in terms of being right or not, that approach would be fine with some modifications. At the end, what happens before the build is called is purely internal to the Builder. It's an implementation matter. The important thing is that the previous rules are met.
To fix rule 4: your Builder.build method should return a deep clone of the temp instance being used (there are ways to achcieve that without needing to specify each field). Or, you should have a flag in builder that forbids calling any other method on Builder instance, once build has been called.
Side note: i usually prefer that Builder class also uses private constructor. I would have this on Person class:
public static Builder builder() {
return new Builder();
}
This can give you more flexibility on the way to initialize the Builder, or even you can have several builder methods doing not exactly the same stuff in terms of "preconfiguring" the builder (and since they are methods, you have more flexibility on naming than on constructors :) )
Is there, in Java, a way to add some fields and methods to an existing class?
What I want is that I have a class imported to my code, and I need to add some fields, derived from the existing fields, and their returning methods.
Is there any way to do this?
You can create a class that extends the one you wish to add functionality to:
public class sub extends Original{
...
}
To access any of the private variables in the superclass, if there aren't getter methods, you can change them from "private" to "protected" and be able to reference them normally.
Hope that helps!
You can extend classes in Java. For Example:
public class A {
private String name;
public A(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
public class B extends A {
private String title;
public B(String name, String title){
super(name); //calls the constructor in the parent class to initialize the name
this.title= title;
}
public String getTitle(){
return this.title;
}
public void setTitle(String title) {
this.title= title;
}
}
Now instances of B can access the public fields in A:
B b = new B("Test");
String name = b.getName();
String title = b.getTitle();
For more detailed tutorial take a look at Inheritance (The Java Tutorials > Learning the Java Language > Interfaces and Inheritance).
Edit: If class A has a constructor like:
public A (String name, String name2){
this.name = name;
this.name2 = name2;
}
then in class B you have:
public B(String name, String name2, String title){
super(name, name2); //calls the constructor in the A
this.title= title;
}
The examples only really apply if the class you're extending isn't final. For example, you cannot extend java.lang.String using this method. There are however other ways, such as using byte code injection using CGLIB, ASM or AOP.
Assuming this question is asking about the equivalent of C# extension methods or JavaScript prototypes then technically it is possible as this one thing that Groovy does a lot. Groovy compiles Java and can extend any Java class, even final ones. Groovy has metaClass to add properties and methods (prototypes) such as:
// Define new extension method
String.metaClass.goForIt = { return "hello ${delegate}" }
// Call it on a String
"Paul".goForIt() // returns "hello Paul"
// Create new property
String.metaClass.num = 123
// Use it - clever even on constants
"Paul".num // returns 123
"Paul".num = 999 // sets to 999
"fred".num // returns 123
I could explain how to do the same way as Groovy does, but maybe that would be too much for the poster. If they like, I can research and explain.
As this is a hot topic these days, I fail to understand certain concept. Please excuse me if I sound stupid but when I tried creating immutable object most of the posts I found following points
Make class final - makes sense
Dont allow mutators (setters) for the attributes - makes sense
Make attributes private - makes sense
Now I fail to understand why we need below points
Make constructor private and provide createInstance method with the same attributes as constructor or factory method ? How does it help ?
Make attributes final - post of the post fail to explain this point and some where I read to avoid the modification accidentally. How can you modify accidentally, when there are no mutators and class is final ? How making an attribute final is helping ?
Instead of factory pattern, can I use builder pattern ?
I am adding my class and test case here :
public final class ImmutableUser {
private final UUID id;
private final String firstName;
private final String lastName;
public ImmutableUser(UUID id, String firstName, String lastName) {
super();
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
/**
* #return the id
*/
public UUID getId() {
return id;
}
/**
* #return the firstName
*/
public String getFirstName() {
return firstName;
}
/**
* #return the lastName
*/
public String getLastName() {
return lastName;
}
}
Test case
public class ImmutableUserTest {
#Test(expected = IllegalAccessException.class)
public void reflectionFailure() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
ImmutableUser user = new ImmutableUser(UUID.randomUUID(), "john", "liu");
Field i =user.getClass().getDeclaredField("firstName");
i.setAccessible(true);
i.set(user, "cassandra");
System.out.println("user " + user.getFirstName()); // prints cassandra
}
}
This test case fails and prints cassandra.
Let me know if I am doing something wrong.
Make constructor private and provide createInstance method with the same attributes as constructor or factory method ? How does it helps ?
Answer: making the constructor private and providing createInstance() (factory method) does not help by itself: it is one of few things you should do in order to allow users to actually use the class and its instances while you still have the control of the way instances are created.
Make attributes final - the post fails to explain this point and somewhere I read to avoid the modification accidentally. How can you modify accidentally, when there are no mutators and class is final ? How making an attribute final is helping ?
Answer: declaring a class as final means that the user can't extend it, so it "blocks" the user from this kind of "workaround". Declaring an attribute as final won't allow the user of the class to change it. It cannot be "modified accidentally", but it can be "modified viciously" using reflection. Let's see an example, say you have:
final public class SomeClass {
final Integer i = 1;
}
from another class you can do as follows:
class AnotherClass {
public static void main (String[] args) throws Exception {
SomeClass p = new SomeClass();
Field i =p.getClass().getDeclaredField("i");
i.setAccessible(true);
i.set(p, 5);
System.out.println("p.i = " + p.i); // prints 5
}
}
Can instead of factory use builder pattern ?
Answer: you can use the builder pattern or any pattern that helps you control the creation of instances of the class.
Further:
If you want to make sure your class is immutable, make sure that any getter returns a deep-copy of the class member. This technique is called "protective/defensive copy". You can read more about it here
I'd start from making attributes final. Making attribute final guarantees that you cannot change the attribute value. I think this is obvious. (I will write additional comment to changing the content of references immutable objects later).
Now, when all your attributes are final they must be initiated via constructor. However some classes have a lot of attributes, so the constructor becomes huge. Moreover sometimes some attributes can be initialized to default values. Attempt to support this causes us to implement several constructors with almost random combination of arguments. However Builder pattern helps us. But how to make user to use Builder instead of direct invocation of constructor? The answer is making constructor private and creating static method that returns builder:
public class Person {
private final String firstName;
private final String lastName;
private final Person mother;
private final Person father;
private Person(String firstName, String lastName, Person mother, Person father) {
// init the fields....
}
public static PersonBuilder builder() {
return new PersonBuilder();
}
public static class PersonBuilder {
// here fields are NOT final
private String firstName;
private String lastName;
private Person mother;
private Person father;
public PersonBuilder bornBy(Person mother) {
this.mother = mother;
return this;
}
public PersonBuilder conceivedBy(Person father) {
this.father = father;
return this;
}
public PersonBuilder named(String firstName) {
this.firstName = firstName;
return this;
}
public PersonBuilder fromFamily(String lastName) {
this.lastName = lastName;
return this;
}
Person build() {
return new Person(name, lastName, mother, father);
}
}
}
And here is the typical usage pattern:
Person adam = Person.builder().named("Adam").build(); // no mother, father, family
Person eve = Person.builder().named("Eve").build(); // no mother, father, family
Person cain = Person.builder().named("Cain").conerivedBy(adam).bornBy(eve); // this one has parents
As you can see builder pattern often is better than factory because it is much more flexible.
I think that you missed one point in your question: references to other (mutable) objects. If for example we add field Collection<Person> children to our Person class we have to care that getChildren() returns either Iterable or at least unmodifirable collection.
Making the constructor private and using the builder pattern are not necessary for immutability. However because your class can't provide setters and if it has many fields, using a constructor with many parameters can be detrimental to readability hence the idea to use the builder pattern (which needs a pervade constructor).
The other answers seem to have missed an important point though.
Using final fields is essential, not only to ensure that they don't get modified, but because otherwise you lose some important thread safety guarantees. Indeed, one aspect of immutability is that it brings you thread safety. If you don't make the fields final your class becomes effectively immutable. See for example Must all properties of an immutable object be final?
I want to build Data main class with subclasses DataClass1(with own subclass Item) and DataClass2 (with own subclass Item1).
public class Data{
public List<DataClass1> dataClass1List = new ArrayList<DataClass1>();
public List<DataClass2> dataClass2List = new ArrayList<DataClass2>();
public class DataClass1{
public String name;
public List<Item> itemList = new ArrayList<Item>();
public class Item{
public String n1;
public String n2;
public String n3;
}
}
public class DataClass2{
public String name;
public List<Item1> item1List = new ArrayList<Item1>();
public class Item1{
public String n5;
public String n6;
}
}
}
When I want to fill main class Data I use this code:
Data data = new Data();
Item itm = new Item;
itm.n1="1";
itm.n2="2";
itm.n3="3";
data.dataClass1List.itemList.add(itm);
and same for dataClass2List
All sub classes must be public
Is there better way to declare and filling up my class Data
Thanks!!!
p.s. Data class and its sub classes contain only variables not methods!
You seem to be confusing some concepts here.
There are no subclasses in your code. DataClass1 and DataClass2 are inner classes of Data, Item is an inner class of DataClass1 and Item1 is an inner class of DataClass2.
There's no visible need for them to be inner classes, and you're best off avoiding inner classes until you're sure you need them and likely until you know Java a bit better.
With these as inner classes, your proposed usage of them will not work, as they're non-static inner classes, and can only be created within the context of an instance of the outer class.
With the class definitions as they are, a translation of your posted usage would be approximately
Data data = new Data();
DataClass1 dc1 = data.new DataClass1();
Item itm = dc1.new Item();
itm.n1="1";
itm.n2="2";
itm.n3="3";
dc1.itemList.add(itm);
data.dataClass1List.add(dc1);
But this is really quite bad (and it may contain mistakes - I have bothered trying to compile it). Having classes with only fields and no methods, and adding data in this way is not a very object-oriented approach at all.
As WirthLuce noted in a comment, you should change the names to represent something in your domain, and create methods to make them do something appropriate rather than just holding data that is manipulated from outside.
Some suggesions:
You should use getter and setter to access the different fields.
public class SomeClass {
private String name;
[...]
public void setName(String name) {this.name = name;}
public String getName() {return name;}
[...]
}
Since the Data classes are public, do they need to be inner class?
To fix this you would need to move the different public class to different files.
All internal lists could be made `final`.
public final List<Item> itemList = new ArrayList<Item>();
You could make a constructor for the class Item.
public class Item {
public Item(String n1,String n2,String n3) {
this.n1 = n1;
this.n2 = n2;
this.n3 = n3;
}
[...]
}