So I have created a simple class in Java like this:
public class Book {
private String author;
private String title;
public Book (String author, String title) {
this.author = author;
this.title = title;
}
}
public void checkInfo
Is there a way to parse a string (property) in order to get Book properties like this, instead of doing bookA.title ?
Book bookA = new Book("George Orwell","Animal Farm")
String property = "title";
System.out.print(bookA.property);
Thanks in adance!
If you really want to access many properties as String, I suggest you using a Map<String, String> like this :
public class Book
{
private Map<String, String> properties = new HashMap();
public void setProperty(String name, String value)
{
properties.set(name,string);
}
public String getProperty(String name)
{
return properties.get(name);
}
}
Now you can use like this :
Book book = new Book();
book.setProperty("title","Animal Farm");
book.setProperty("author","George Orwell");
System.out.println("Book: " + book.getProperty("title") + " by " + book.getProperty("author"))
You've created your Book as an object.
So, treat it like an object and add getters and setters.
In this case, that would be a method, getTitle() and a separate method getAuthor().
For more information on getters and setters, see the responses to this previous StackOverflow post
You can use reflection:
Field f = bookA.getClass().getDeclaredField("title");
f.setAccessible(true);
String title = (String) f.get(bookA);
System.out.println(title);
First of all, your code won't work because title is private. Second, I have no idea why you set Book class as static. Last, this (Java) is object oriented programming, so treat it like an object.
When you create a class you also add Getters & Setters to access the information inside. The code would look like this:
Class:
public class Book {
private String author;
private String title;
public Book (String author, String title) {
this.author = author;
this.title = title;
}
}
public String getTitle(){
return this.title;
}
public String getAuthor(){
return this.author;
}
Accessing the data:
Book bookA = new Book("George Orwell","Animal Farm")
System.out.print("Book: " + bookA.getTitle() + " by " + bookA.getAuthor());
This would return :
Book: Animal Farm by George Orwell
If you see these few lines from your code:
private String author; // both are private variables
private String title;
Here author and title both are private String . So you can't access these properties outside of the class.
So, you'll need to add public getters and setters that can be used to access the properties.
you should change you Object class.. add getter and setter method..
here is example :
public class Book{
String myauthor;
String mytitle;
public Book (String author, String title){
myauthor=author;
mytitle=title;
}
public void setAuthor(String Autor){
myauthor=author;
}
public String getAuthor(){
return myauthor;
}
}
and create setter and getter for 'title' too..
if you want to get the title / author, just simply call
Book.getAuthor();
If you don't want to have getter/setter method for your class ;you can define access modifier as protected with static keyword.For example is:
under com.test package-There are two class.One is Book class and other is BookInSamePackage class.In Book class;if you define attribute title as protected static String title then in BookInSamePackage class ;You can access like that :'Book.title'.If you want to use this title attribute in class of another package;then this class need to extend Book class and can access like this way:Book.title in child class of another package.
Related
What im trying to do is have the user input an index of "record" they want to append. The index will be used to look at a specific object in the array list. Everything stored in that object will be written to the input from. The user will then be able to append their input and write it back to the same object. What I'm stuck on is the taking data from the object and adding it to the form controls. I was am using
Movie genreOfMovie = (Movie) movieList.get(Integer.parseInt(index) - 1);
but that gave me object instance which is not a string that I wanted.
I was told to use
#Override
public String toString() {
return genreOfMovie;
}
It worked but only for that veritable, is there a way to make it work for all the variables in the selected object?
If you have a text field (for instance for the title of the movie) I suggest you add setTitle(String newTitle) and getTitle() to your Movie class.
With this in place, you can do
textField.setText(selectedMovie.getTitle());
and, when the user clicks save,
selectedMovie.setTitle(textField.getText());
If you have more properties (genre, director, ...) I suggest you add more get-/set-methods.
Unless the class has an very obvious String-representation, the toString should only be used in debugging purposes.
If you want to get all variables data from Movie object,
either
include a method inside Movie object which appends the variables data in required format and gives as String output.
or
Write your own method which will take Movie object as an input, and calls required fields getter methods like getTitle()+getGenreOfMovie+getLength() like that and return a String object.
And important thing is to check for Null or Empty data inside those variables.
import java.util.ArrayList;
import java.util.List;
public class MovieTest {
public static void main(String[] args) {
List<Movie> movies = new ArrayList<Movie>();
movies.add(new Movie("A"));
movies.add(new Movie("B"));
movies.add(new Movie("C"));
Movie movie = movies.get(1);
System.out.println(movie);
movie.setDirector("Director for B");
movie = movies.get(1);
System.out.println(movie);
}
}
class Movie {
String title;
String director;
int length;
Movie(String title) {
this.title = title;
}
public String getTitle() { return title; }
public String getDirector() { return director; }
public int getLength() { return length; }
public void setTitle(String title) { this.title=title; }
public void setDirector(String director) { this.director = director; }
public void setLength(int length) { this.length = length; }
public String toString() {
return "[" + title + "]["+ director +"][" + length + "]";
}
}
package book1;
import java.util.ArrayList;
public abstract class Book {
public String Book (String name, String ref_num, int owned_copies, int loaned_copies ){
return;
}
}
class Fiction extends Book{
public Fiction(String name, String ref_num, int owned_copies, String author) {
}
}
at the moment when i input values into the variable arguments and call them with this :
public static class BookTest {
public static void main(String[] args) {
ArrayList<Book> library = new ArrayList<Book>();
library.add(new Fiction("The Saga of An Aga","F001",3,"A.Stove"));
library.add(new Fiction("Dangerous Cliffs","F002",4,"Eileen Dover"));
for (Book b: library) System.out.println(b);
System.out.println();
}
}
i get a return value of this:
book1.Fiction#15db9742
book1.Fiction#6d06d69c
book1.NonFiction#7852e922
book1.ReferenceBook#4e25154f
how can i convert the classes to return a string value instead of the object value? I need to do this without changing BookTest class. I know i need to use to string to convert the values. but i don't know how to catch the return value with it. could someone please point me in the right direction on how to convert this output into a string value?
You need to overwrite the toString() Method of your Book class. In this class you can generate a String however you like. Example:
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(this.author).append(": ").append(this.title);
return sb.toString();
}
You need to override the toString() method in your Book or Fiction class. The method is actually declared in the Object class, which all classes inherit from.
#Override
public String toString(){
return ""; // Replace this String with the variables or String literals that you want to return and print.
}
This method is called by System.out.println() and System.out.print() when they receive an object in the parameter (as opposed to a primitive, such as int and float).
To reference the variables in the method, you'll need to declare them in the class and store them via the class's constructor.
For example:
public abstract class Book {
private String name;
private String reference;
private int ownedCopies;
private int loanedCopies;
public Book (String name, String reference, int ownedCopies, int loanedCopies) {
this.name = name;
this.reference = reference;
this.ownedCopies = ownedCopies;
this.loanedCopies = loanedCopies;
}
#Override
public String toString(){
return name + ", Ref:" + reference + ", OwnedCopies: " + ownedCopies + ", LoanedCopies: " + loanedCopies; // Replace this String with the variables or String literals that you want to return and print.
}
}
The classes you have defined, don't store any values. It is in other words useful to construct a new book. You need to provide fields:
public abstract class Book {
private String name;
private String ref_num;
private int owned_copies;
private int loaned_copies;
public String Book (String name, String ref_num, int owned_copies, int loaned_copies) {
this.name = name;
this.ref_num = ref_num;
this.owned_copies = owned_copies;
this.loaned_copies = loaned_copies;
}
public String getName () {
return name;
}
//other getters
}
Now an object is basically a set of fields. If you want to print something, you can access and print one of these fields, for instance:
for (Book b: library) System.out.println(b.getName());
In Java, you can also provide a default way to print an object by overriding the toString method:
#Override
public String toString () {
return ref_num+" "+name;
}
in the Book class.
Need to give your object Book a ToString() override.
http://www.javapractices.com/topic/TopicAction.do?Id=55
Example:
#Override public String toString()
{
return name;
}
Where name, is a string in the Class.
I am hoping that you have assigned the passed arguments to certain attributes of the classes. Now, once you are done with that, you can override the toString() method in Book to return your customized string for printing.
I am making a simple program that sets the title and name of an object: book1. Eventually, the goal is to have several books under the Patron class that will use the Book class to assign values. However, I am running into difficulty simply getting the Patron class to acknowledge the Book class methods.
Basic Tester/Main method:
import java.util.Scanner;
public class ProjectFiveSix {
public static void main(String[] args) {
String title = "Bob";
String name = "Hugo"; // name of patron (class assigning book)
String author = "Rodrigo";
Patron patronOne = new Patron();
patronOne.setName(name);
Patron Class :
public class Patron {
private String name;
private Book book1;
private Book book2;
private Book book3;
public Patron(){
name = "";
book1 = null;
book2 = null;
book3 = null;
}
public String setName(String name){
return name;
}
public String borrowBook(String book1, String titleFinal, String authorFinal, String title, String author){
if (book1 == null){
book1.setTitle(titleFinal); //**
book1.setAuthor(authorFinal); //***
}
}
}
Book Class:
public class Book {
private String titleFinal;
private String authorFinal;
public Book(){
titleFinal = "";
authorFinal = "";
}
public String setTitle(String title){
titleFinal = title;
return titleFinal;
}
public String setAuthor(String author){
authorFinal = author;
return authorFinal;
}
}
Here I am getting "Cannot find Symbol" on both lines book1.settitle and book1.setauthor. The book has been instantiated and I cannot figure out the problem.
Thanks in advance!
You declared your parameter book1 (a String) as the same name as your instance variable book1 (a Book). To reference the instance variable, either name the parameter a different variable name, or use this. to specify the instance variable:
this.book1.setTitle(titleFinal); //**
this.book1.setAuthor(authorFinal); //***
Either way, you'll need to create an actual Book instance, or else your instance variable book1 will remain null and you'll get a NullPointerException.
Problem Description
I have an abstract Paper class that contains common properties of all papers and one or more child classes of paper that add additional information for that type of paper. I then have a HashMap<String, Paper> to store multiple papers.
My application allows the user to update a paper by providing a the pid and then supplying the attributes and values to update. The issue I am having is how do I update the properties on the sub classes when all I have is the super class.
What is the best way/practice to handle this situation?
Class Structure
public abstract class Paper {
String pid;
String title;
String author;
}
public class Publication extends Paper {
int pages;
}
public class PHDThesis extends Paper {
String supervisor;
}
My Current Attempt
This is what I currently have** and it works by using instance of; but I feel there should be a better way to do this.
import java.util.*;
public class App {
public static abstract class Paper {
private String title;
private String author;
public Paper(String title, String author) {
this.title = title;
this.author = author;
}
public void update(String title, String author) {
this.title = title;
this.author = author;
}
}
public static class Publication extends Paper {
private int pages;
public Publication(int pages, String title, String author) {
super(title, author);
this.pages = pages;
}
public void update(String title, String author, int pages) {
super.update(title, author);
this.pages = pages;
}
}
public static class PHDThesis extends Paper {
private String supervisor;
public PHDThesis(String supervisor, String title, String author) {
super(title, author);
this.supervisor = supervisor;
}
public void update(String title, String author, String supervisor) {
super.update(title, author);
this.supervisor = supervisor;
}
}
public static void main(String[] args) {
HashMap<String, Paper> papers = new HashMap<String, Paper>();
papers.put("P001", new PHDThesis("My Super", "My PHD Title", "My Author"));
papers.put("P002", new Publication(22, "My Pub Title", "My Author"));
Paper p = papers.get("P001");
if (p instanceof PHDThesis) {
((PHDThesis)p).update("New Title", "New author", "New Super");
} else if (p instanceof Publication) {
((Publication)p).update("New Title", "New author", 33);
}
}
}
** reduced test code, actual code is much more complex and better laid out.
You can create an object called UpdateBundle with getters for each attribute.
Then the Paper class will have a method update(UpdateBundle) which each child will implement differently.
All you have to do is call that method for each child and they will know how to handle it.
On a separate note, i don't see why the paper class is abstract. You seem to have no abstract methods in it.
public abstract class Paper {
String pid;
String title;
String author;
public void update(PaperUpdateBundle bundle)
{
pid = bundle.getPID();
title = budnle.getTitle();
author = bundle.getAuthor();
}
}
public class Publication extends Paper {
int pages;
public void update(PaperUpdateBundle bundle)
{
super.update(bundle);
pages = bundle.getPages();
}
}
public class PHDThesis {
String supervisor;
public void update(PaperUpdateBundle bundle)
{
super.update(bundle);
supervisor = bundle.getSupervisor();
}
}
public interface PaperUpdateBundle
{
String getPID();
String getTitle();
String getAuthor();
int getPages();
String getSupervisor();
}
Create a method
public void update( Map<String, Object> parameters );
to all Papers and pull the relevant properties from it in the Paper implementations.
In Publication it might look like:
public void update( Map<String, Object> parameters ) {
super.update( parameters );
this.pages = parameters.get( "pages" );
}
The problem with the accepted answer is that it requires you to update all of the properties manually. If the list of properties changes, you have to change the update() method or things will get out of sync. In my experience this happens frequently. And then you've got to spend a lot of time trying to track down the bug.
A different way (I won't call it a "better" way) is to use reflection or some third party library to copy the fields. There are some tradeoffs, though. The advantage is that your code requires a lot less work and will (probably) have fewer bugs. The downside is that your code will be slower, less flexible, and lack compile-time checks.
I have sometimes used Jackson's ObjectMapper.convertValue() to do this. You can find other ways to do it here: Copy all values from fields in one class to another through reflection.
Since my post yesterday regarding constructing a link list from scratch I have made some progress.
I have encountered a new hurdle: storing an object within an object.
Lets say I have a 'book' class with the following attributes (forgetting all the set & get methods which I am familiar with):
private String title;
private int rating;
How would I then reference another class such as 'author' as obviously a book must have an author and many books may have the same or more then one author.
Here is my 'author' class attributes (again ignoring gets & sets):
String authorName;
String authorEmail;
Am I right in thinking I need to initiate an object of 'author' within the 'book' class as such:
private String title;
private int rating; //mine
private Author author = new Author();
Would I then have to set the attributes authorName and authorEmail everytime I made a new instance of 'book'?
Many thanks in advance for constructive feedback.
You don't necessarily need to instantiate the Author object right there where you declare the attribute. I would suggest something like passing in an already-instantiated Author either to the constructor of the Book class or to a setter. Then you could pass the same Author in to each Book you create that should be associated with it.
EDIT: added some code snippets:
For instance, if you made your Book constructor something like this:
public Book(String title, int rating, Author author) {
// set this.title, this.rating, and this.author to the passed-in parameters...
}
Then you would invoke it in code like this:
Author bob = new Author();
// You can set the name and email of the Author here using setters,
// or add them as args in the Author constructor
Book firstBook = new Book("The First Book", 1, bob);
Book secondBook = new Book("The Second Book", 2, bob);
This is a many to many relationship. You need your Author class to simply be a link between a person and a book. Then things will work out.
You might want some kind of singleton author list in order to prevent many copies of the same author. Either that, or you will definitely need to override the equals method of author.
If you use a singleton, you could have a getAuthor routine in your AuthorList object that either makes an author if it doesn't exist or fetches the already created author.
Your on the right track. You can use an ArrayList to be able to dynamically add new authors without having to resize anything. Let me clarify it for you:
class Book {
private String title;
private int rating;
private List<Author>authors = new ArrayList<Author>();
public Book(String title, int rating, Author author) {
this.title = title;
this.rating = rating;
authors.add(author);
}
public Book(String title, int rating, Author author) {
this.title = title;
this.rating = rating;
this.author = author;
}
public void addAuthor(Author a) {
authors.add(a);
}
public int numberOfAuthors() {return authors.size();}
}
class Author {
private String name;
private String email;
public Author(String name, String email) {
//...Same thing
}
}
class Main {
public static void main(String[] args) {
Book book = new Book("Java Programming", 5, new Author("Me", "me#gmail.com"));
Author contributingAuthor = new Author("My Friend", "cupcakes#gmail.com");
book.addAuthor(contributingAuthor);
}
}