I am very new in java reflection and generic types. I am now developing database handler library for android. I am stuck at returning array list from reflection.
for example:
This class is the library user's class
public class Creation extends SimpleDBHandler<Creation> {
private String tools;
private String nature;
public Creation(String tools,String nature) {
this.tools = tools;
this.nature = nature;
}
public String getTools() {
return tools;
}
public void setTools(String tools) {
this.tools = tools;
}
public String getNature() {
return nature;
}
public void setNature(String nature) {
this.nature = nature;
}
}
This class is the library user class
usage:
public class Main {
public static void main(String[] args) {
ArrayList<Creation> arrList = new ArrayList<>();
arrList = new SimpleDBHandler<Creation>().getAllData(Creation.class);
}
}
This is library class
public class SimpleDBHandler<T> {
public <T extends SimpleDBHandler<?>> ArrayList<T> getAllData(Class<?> mClass) {
ArrayList<T> arrList = new ArrayList<>();
// I am suck here. How to add data to arrList?
return arrList;
}
}
Please help me. Thanks before.
Related
I'm a newbie in java and I have to do a "array project" for college. I'm having trouble getting the array in my Main class from Contacts class where it is stored. This is what I've done for now:
public class Main {
public static void main(String[] args) {
// View Contact Testing
Contacts contactObj = new Contacts();
System.out.println(contactObj);
}
}
public class Contacts {
public static void main(String[] args) {
ArrayList<String> arr = new ArrayList<String>();
arr.add("name1");
arr.add("name2");
return arr.clone();
}
}
When I run this, I get this error: Error:(11, 25) java: incompatible types: unexpected return value.
Any help would be much appreciated,
Thanks
As suggested by others I also advice you study a little bit more in some basic Java tutorials (there is a several spread over www). But also I understanding your struggling and will give you a few example that how you could do that. Follow:
Main.java
public class Main {
public static void main(String[] args) {
Contacts contactObj = new Contacts();
contactObj.getNames().forEach(System.out::println);
contactObj.cleanNames();
contactObj.getNames().forEach(System.out::println);
contactObj.addName("John");
contactObj.addName("Maria");
contactObj.getNames().forEach(System.out::println);
}
}
Contacts.java
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class Contacts {
private List<String> names;
//either to help your understanding and for sake of simplicity
public Contacts() {
this.names = new ArrayList<String>();
this.names.add("name1");
this.names.add("name2");
}
//clean the content of names from names List
public void cleanNames(){
if (Objects.nonNull(names)) {
this.names.clear();
}
}
//add a name to list
public void addName(String name) {
if (Objects.nonNull(names)) {
this.names.add(name);
} else {
this.names = new ArrayList<>();
this.names.add(name);
}
}
//set a entire list to names attribute
public void setNames(List<String> names) {
this.names = names;
}
//get the name attribute
public List<String> getNames() {
if (Objects.nonNull(names)) {
return this.names;
} else {
this.names = new ArrayList<>();
return names;
}
}
}
i wanted to know if you can create a method inside a class that can create more than 1 list
public class UnidadeSaude {
private String NomeUnidade;
public UnidadeSaude() {
}
public UnidadeSaude(String NomeUnidade) {
this.NomeUnidade = NomeUnidade;
}
public String getNomeUnidade() {
return NomeUnidade;
}
public void setNomeUnidade(String nomeUnidade) {
NomeUnidade = nomeUnidade;
}
void gravar(String NomeUnidade){
List<String> UnidadeSaude = new ArrayList<String>();
UnidadeSaude.add(NomeUnidade);
}
void ler() {
System.out.print(UnidadeSaude);
}
}
First: in Java, variable names are written in camelCase and Classes in PascalCase.
This is extremely important to difference between objects and Class references.
Second: I think you're trying to write names into a List in the gravar() method.
You can do it by having a static List in the class. You can add them to the list and then print them in the ler() method.
public class UnidadeSaude {
private String nomeUnidade;
private static List<String> nomeUnidades = new ArrayList();
public UnidadeSaude() {
}
public UnidadeSaude(String nomeUnidade) {
this.nomeUnidade = nomeUnidade;
}
public String getNomeUnidade() {
return nomeUnidade;
}
public void setNomeUnidade(String nomeUnidade) {
this.nomeUnidade = nomeUnidade;
}
void gravar(String NomeUnidade) {
nomeUnidades.add(NomeUnidade);
}
void ler() {
for (String nome : nomeUnidades) {
System.out.println(nome);
}
}
}
HOWEVER, I don't recommend this! It doesn't semantically make sense to store multiple objects into a class that represents a single object. You should ideally store them in a List outside that class
I am at my last year at the university and working on my final project with a group of friends.
I am responsible on implementing the database (using google firestore in java) and i am trying to implement it using a design pattern.
I found the adapter quiet useful, as I can create an interface called:
GenericDB, which contains all the methods the database needs to use.
A concrete class, let's call her FirestoreDB which implements it,
and an Adapter, which also implements the GenericDB, and holds an Instance Of GenericDB as a variable, so I can choose at run time which db I will want to use (maybe in the future the db would change)
Here is some basic code:
public interface GenericDB {
boolean add(String... args);
boolean delete(String... args);
boolean get(String... args);
boolean changePassword(String... args);
}
public class FirestoreDB implements GenericDB {
private final Firestore db;
public FirestoreDB() {
FirestoreOptions firestoreOptions =
FirestoreOptions.getDefaultInstance().toBuilder()
.setProjectId(Constants.PROJECT_ID)
.build();
this.db = firestoreOptions.getService();
}
public boolean add(String... args) {
return true;
}
public boolean delete(String... args) {
return false;
}
public boolean get(String... args) {
return false;
}
public boolean changePassword(String... args) {
return false;
}
}
public class Adapter implements GenericDB {
private GenericDB db;
public Adapter(GenericDB db){
this.db = db;
}
public boolean add(String... args) {
return this.db.add(args);
}
public boolean delete(String... args) {
return db.delete(args);
}
public boolean get(String... args) {
return db.get(args);
}
public boolean changePassword(String... args) {
return db.changePassword(args);
}
}
public class DatabaseCreator {
public GenericDB getDB(DATABASE database) {
switch (database) {
case FIRESTORE:
return new FirestoreDB();
default:
return null;
}
}
DatabaseCreator database = new DatabaseCreator();
GenericDB db = database.getDB(EXTRA.DATABASE.FIRESTORE);
Adapter ad = new Adapter(db);
System.out.println(ad.add("1"));
Is this a good use of the adapter pattern?
Is this a good use of the adapter pattern?
What you call Adapter, is not an Adapter. Purpose of Adapter is to convert interface of the class to another interface expected by the client. But your 'adapter' implements the same GenericDB interface as the adaptee it wraps - no conversion happens here.
The closest one to Adapter is your FirestoreDB class. It is intended to convert the interface of Firestore to the interface GenericDB required by your code. Of course there is still small chance that Google will change Firestore to implement your GenericDB interface. Until then you should use an adapter.
To make FirestoreDB a proper adapter, you should pass adaptee (Firestore object) to the constructor of adapter, and later call it in the GenericDB methods implementation:
public class FirestoreAdapter implements GenericDB {
private final Firestore db;
public FirestoreAdapter(Firestore db) { // pass adaptee to adapter
this.db = db;
}
public boolean add(...) {
// DocumentReference docRef = db.collection(colName).document(docId);
// etc
}
// etc
}
This adapter could be passed to the code which expects GenericDB interface and knows nothing about Firestore interface:
FirestoreOptions firestoreOptions =
FirestoreOptions.getDefaultInstance().toBuilder()
.setProjectId(Constants.PROJECT_ID)
.build();
Firestore firestore = firestoreOptions.getService(); // but your code requires GenericDB
GenericDB db = new FirestoreAdapter(firestore); // adapt Firestore interface
// use db here as if Firestore was implementing your GenericDB interface
You can write adapters for another type of database in the same way. But... usually, you don't use some abstract database interface, because databases are very different with different sets of features. Trying to find some intersection of features supported by all databases might be not a great idea (unless you writing CosmosDB). Usually, you will work with higher-level abstractions, like Repositories.
You should use Command Design Pattern it more flexible than Adapter in your case
Example:
import java.util.HashMap;
import java.util.Map;
// demo for firestore
class Firestore {
private Map<Object, Object> map = new HashMap<>();
public void add(Object id, Object object) {
map.put(id, object);
}
public Object get(Object id) {
return map.get(id);
}
}
interface FirestoreAware {
void setFirestore(Firestore firestore);
}
enum CommandType {
ADD,
DELETE,
GET,
CHANGE_PASSWORD,
GET_USER
}
interface Command {
CommandType getType();
}
class GetCommand implements Command {
private int id;
public GetCommand id(int id) {
this.id = id;
return this;
}
public int getId() {
return id;
}
#Override
public CommandType getType() {
return CommandType.GET;
}
}
class AddCommand implements Command {
private int id;
private String jsonData;
public AddCommand id(int id) {
this.id = id;
return this;
}
public AddCommand jsonData(String jsonData) {
this.jsonData = jsonData;
return this;
}
public int getId() {
return id;
}
public String getJsonData() {
return jsonData;
}
#Override
public CommandType getType() {
return CommandType.ADD;
}
}
interface CommandHandler<C> {
Object handle(C cmd);
}
abstract class CommandFirestoreHandler<C>
implements CommandHandler<C>, FirestoreAware {
protected Firestore firestore;
#Override
public void setFirestore(Firestore firestore) {
this.firestore = firestore;
}
}
class AddCommandHandler extends CommandFirestoreHandler<AddCommand> {
#Override
public Object handle(AddCommand cmd) {
firestore.add(cmd.getId(), cmd.getJsonData());
return Boolean.TRUE;
}
}
class GetCommandHandler extends CommandFirestoreHandler<GetCommand> {
#Override
public Object handle(GetCommand cmd) {
return firestore.get(cmd.getId());
}
}
interface GenericDB {
<T> T execute(Command cmd);
}
class FirestoreDB implements GenericDB {
private final Firestore firestore;
private final Map<CommandType, CommandHandler> handlers;
public FirestoreDB() {
this(new Firestore());
}
public FirestoreDB(Firestore firestore) {
this.firestore = firestore;
this.handlers = new HashMap<>();
// demo add default command handlers
this.addHandler(CommandType.ADD, new AddCommandHandler());
this.addHandler(CommandType.GET, new GetCommandHandler());
}
public void addHandler(CommandType commandType, CommandHandler handler) {
if(handler instanceof FirestoreAware)
((FirestoreAware)handler).setFirestore(firestore);
this.handlers.put(commandType, handler);
}
#Override
public <T> T execute(Command cmd) {
CommandHandler handler = handlers.get(cmd.getType());
return (T)handler.handle(cmd);
}
}
class DatabaseCreator {
public GenericDB getDB(String database) {
switch (database) {
case "FIRESTORE":
return new FirestoreDB();
default:
return null;
}
}
}
public class GenericDBDemo {
public static void main(String[] args) {
DatabaseCreator database = new DatabaseCreator();
GenericDB db = database.getDB("FIRESTORE");
db.execute(new AddCommand().id(1).jsonData("{'_id': 1, 'name' : 'hello world'}"));
System.out.println(db.execute(new GetCommand().id(1)).toString());
}
}
I have created a web service and deplyed it on GlassFish on localhost.
#WebService
public class ProductCatalog {
ProductServiceImpl productService = new ProductServiceImpl();
public boolean addProductCategories(String category) {
return productService.addCategory(category);
}
public List<String> getProductCategories() {
return productService.getCategories();
}
}
My service class
public class ProductServiceImpl {
List<String> categories = new ArrayList<>();
public boolean addCategory(String categoryName) {
return categories.add(categoryName);
}
public List<String> getCategories() {
return categories;
}
}
Through the GF admin panel I checked both methods. They work. I can add a category or get all existing categories.
After that I imported the wsdl and got following classes.
Then I created a new project and added imported classes to it.
public class DataController {
public static void main(String[] args) {
String category = "Horror";
ProductCatalog productCatalog = new ProductCatalog() {
public boolean addProductCategories(String arg0) {
return false;
}
public List<String> getProductCategories() {
return null;
}
};
productCatalog.addProductCategories(category);
ProductCatalogService productCatalogService = new ProductCatalogService();
}
}
Now I wan't to add a new category, but have no idea how to do it.
This
productCatalog.addProductCategories(category);
doesn't work. The app runs, but when checking existing categories through GF admin panel, I see that none were added.
What is the reason?
I was using the wrong way. This is how it should be.
public class DataController {
public static void main(String[] args) {
String category = "Anime";
ProductCatalogService productCatalogService = new ProductCatalogService();
ProductCatalog productCatalog = productCatalogService.getProductCatalogPort();
productCatalog.addProductCategories(category);
List<String> categories = productCatalog.getProductCategories();
for(String categoryName : categories){
System.out.println(categoryName);
}
}
}
I'm java virgin. I've made really simple code like below.
class TreeData implements Comparable<TreeData> {
private String sixString;
private ArrayList<Integer> stringNum = new ArrayList<Integer>();
private ArrayList<Integer> charNum = new ArrayList<Integer>();
public TreeData(String sixString, int stringNum, int charNum){
this.sixString = sixString;
(this.stringNum).add(stringNum);
(this.charNum).add(charNum);
}
public int compareTo(TreeData other) {
return sixString.compareTo(other.getSixString());
}
public String getSixString(){
return sixString;
}
}
class Child<T extends Comparable<T>>{
public void print(T data){
//error : String a = data.getSixString();
System.out.println("hi");
}
}
public class Test {
public static void main(String[] args) {
Child<TreeData> child = new Child<TreeData>();
TreeData td = new TreeData("sixString", 8, 2);
child.print(td);
}
}
I had a problem in 'print' method in the Child class. When I tried calling the getSixString() method of data(passed as argument), it occurs error. I don't know why I can't using public method in the argument 'data'. Is it related with Generic? Thanks, in advance.
In your Child class, you only define T to be extending Comparable. Yet you expect it to have the method getSixString which Comparable doesn't have. What you probably want it for it to be extending TreeData:
class Child<T extends TreeData>{
public void print(T data){
String a = data.getSixString();
//should work now since T defines getSixString()
}
}
Or better yet if all you want is for T to be TreeData, you don't need any generic class. I'm assuming your real intention was:
class Child extends TreeData {
public void print(){
String a = getSixString();
}
}