I am attempting to reference a variable in a method in my class and keep running into a NullPointerException. I know it is happening at the variable pbook when it is referenced from the addPerson method. Why is this happening and how could I go about fixing it?
public class Phonebook <T> {
private LinkedList<T> pbook;
public T findPerson(T person) {
for (int i = 0; i < pbook.size(); i++) {
if (pbook.get(i).equals(person)) {
return person;
}
else
{
i++;
}
}
return null;
}
public void addPerson(T person) {
pbook.addFirst(person);
}
public void deletePerson(T person) {
for (int i = 0; i < pbook.size(); i++) {
if (pbook.get(i).equals(person)) {
pbook.remove(i);
}
else
{
i++;
}
}
}
/**
* #param args
*/
public static void main(String[] args){
try{
Phonebook<Integer> sspb = new Phonebook<Integer>();
Phonebook<String> idpb = new Phonebook<String>();
sspb.addPerson(1234567890);
idpb.addPerson("Bob");
}
catch (Exception e){
e.printStackTrace();
}
}
}
You must add a constructor to instantiate your LinkedList:
public Phonebook() {
pbook = new LinkedList<T>();
}
Change:
private LinkedList<T> pbook;
To:
private LinkedList<T> pbook = new LinkedList<T>();
private LinkedList<T> pbook; You don't create a list.
Try this.
private LinkedList<T> pbook = new LinkedList<T>()
1) You can define a constructor e.g. like this.
public Phonebook(LinkedList<T> pbook){
this.pbook = pbook;
}
Then the calling code will have to set the
pbook when instantiating the Phonebook.
2) You can initialize pbook where you declare it.
private LinkedList<T> pbook = new LinkedList<T>();
Related
I have an entity that has as children several lists of objects that, although they have different classes, all have the order attribute, in several parts I end up with repeated code, for example in one part I need to order the lists by that attribute and I cannot simplify because they are of different type.
The relevant part of the entity is this:
contenido={
"educaciones":[
{
...
"orden":0
},{
...
"orden":1
}
],
"experiencias":[
{
...
"orden":0
},{
...
"orden":1
}
]
},
...
The code I would like to simplify:
if(tipo.equals("experiencias")){
List<Experiencia> iterable=contenido.getExperiencias();
for(int i = 0; i < iterable.size(); i++){
iterable.get(i).setOrden( orden.get(i) ); //orden = [0,3,5,...]
}
iterable.sort((it1,it2)-> it1.getOrden().compareTo(it2.getOrden()));
}else if(tipo.equals("educaciones")){
List<Educacion> iterable=contenido.getEducaciones();
for(int i = 0; i < iterable.size(); i++){
iterable.get(i).setOrden( orden.get(i) );
}
iterable.sort((it1,it2)-> it1.getOrden().compareTo(it2.getOrden()));
}else if...
Is there a way to create a code that is more generic and supports different objects?
Create an interface for the methods that are common between all you classes:
interface HasOrden {
int getOrden();
void setOrden(int i);
}
Each of your classes needs to implement HasOrden.
Then you can declare sortOrden function:
import java.util.ArrayList;
import java.util.List;
interface HasOrden {
int getOrden();
void setOrden(int i);
}
class Experiencia implements HasOrden {
private final String name;
int orden;
public Experiencia(String name) {
this.name = name;
}
#Override
public int getOrden() {
return orden;
}
#Override
public void setOrden(int i) {
orden = i;
}
public String toString() {
return name;
}
}
public class Eg {
static void sortOrden(List<? extends HasOrden> l, List<Integer> order) {
if (l.size() != order.size()) {
throw new RuntimeException("length mismatch");
}
for (int i = 0; i < l.size(); i++) {
l.get(i).setOrden(order.get(i));
}
l.sort((it1,it2)-> Integer.compare(it1.getOrden(), it2.getOrden()));
}
public static void main(String[] args) {
List<Experiencia> items = new ArrayList<>(List.of(new Experiencia("a"), new Experiencia("b")));
List<Integer> order = List.of(2,1);
sortOrden(items, order);
System.out.println(items);
}
}
You can call sortOrden on any list of HasOrden instances.
you can try to create a List<?> - list with a dynamic type outside of your if else block and move your duplicated code outside too and at the end of the if else block. In addition, you have to create a common class or some interface for your classes, which holds all the common field you needed
public class Main {
public static class Something {
private Integer sth;
public Integer getSth() {
return sth;
}
public void setSth(Integer sth) {
this.sth = sth;
}
}
public static class ThisClass extends Something {
private Integer num;
public ThisClass(Integer num) {
this.num = num;
}
public Integer getNum() {
return num;
}
public void setNum(Integer num) {
this.num = num;
}
}
public static class ThatClass extends Something {
private String str;
public ThatClass(String str) {
this.str = str;
}
public String getStr() {
return str;
}
public void setNum(String str) {
this.str = str;
}
}
public static List<? extends Something> sortList(Class<?> itemClass, List<? extends Something> list)
throws Exception {
for(int i = 0; i < list.size(); i++){
list.get(i).setSth(i);
}
list.sort((it1,it2)-> it1.getSth().compareTo(it2.getSth()));
return list;
}
public static void main(String[] args) {
System.out.println("Hello World");
List<? extends Something> someList = new ArrayList<>();
boolean check = true;
if(check) {
someList = Arrays.asList(new ThisClass(1),new ThisClass(1),new ThisClass(1),new ThisClass(1));
} else {
someList = Arrays.asList(new ThatClass("a"), new ThatClass("a"),new ThatClass("a"),new ThatClass("a"));
}
try {
someList = sortList(ThisClass.class, someList);
for(int i = 0; i < someList.size(); i++){
System.out.println(someList.get(i).getSth());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
I need a function to create instances of a dynamically given class in java.
I had found many samples but in all of them, the class to be instantiated was known before runtime.
There are user defined classes:
class Student { //some code }
class Teacher { //some code }
class Course { //some code }
What I need is
List<class> MyFunction(<class>) {
List<class> items = new ArrayList<class>();
for(int i = 0; i < 5; i++) {
create_a_new_class_instance;
items.add(new_created_instance);
}
return items;
}
How will I use
List<Student> students = MyFunction(Student);
List<Teacher> teachers = MyFunction(Teacher);
List<Course> courses = MyFunction(Course);
Hope someone helps.
This is my first question in Stackoverflow, sorry for any inconvenience.
Utku
In Java 8, you can use a method reference or lambda expression in order to create instances of classes dynamically without using reflection.
public static <T> List<T> myFunction(Supplier<T> supplier) {
return Stream.generate(supplier)
.limit(5)
.collect(Collectors.toList());
}
You would call it like:
List<Student> students = myFunction(Student::new);
If you're not familiar with streams, the imperative equivalent is:
public static <T> List<T> myFunction(Supplier<T> supplier) {
int size = 5;
List<T> list = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
list.add(supplier.get());
}
return list;
}
This should work.
import java.util.ArrayList;
import java.util.List;
public class DynamicClassList {
public <T> List<T> myFunction(Class<T> inputClass) {
List<T> items = new ArrayList<T>();
for(int i = 0; i < 5; i++) {
try {
T myT = inputClass.getConstructor().newInstance();
items.add(myT);
} catch (Exception e) {
e.printStackTrace();
}
}
return items;
}
public static void main(String[] args) {
DynamicClassList dynamicClassList = new DynamicClassList();
List<Student> s = dynamicClassList.myFunction(Student.class);
List<Teacher> t = dynamicClassList.myFunction(Teacher.class);
List<Course> c = dynamicClassList.myFunction(Course.class);
}
}
Assuming that the classes supplied to MyFunction have a default constructor, a simple implementation would be
public static <T> List<T> MyFunction(Class<T> clazz) {
if (clazz == null) {
return null;
}
T item;
List<T> items = new ArrayList<T>();
for (int i = 0; i < 5; i++) {
try {
item = clazz.newInstance();
} catch (Exception e) {
item = null;
}
if (item != null) {
items.add(item);
}
}
return items;
}
and the above method could be called like
List<Student> student = MyFunction(Student.class);
For increased transparency, the exception thrown inside the method could be handled in another way (e.g., added to the method signature).
You could use reflection to do this
each class you pass must have a default no-argument constructor.
for this specific application you will likely need all 3 classes to share an interface so that you can properly send a list back
public interface Unit {
//Put any common functionality method stubs here
}
public class Teacher implements Unit {
}
//....etc for the other classes
List<Unit> MyFunction(Class<Unit> clazz) {
List<Unit> items = new ArrayList<Unit>();
for(int i = 0; i < 5; i++) {
items.add(clazz.newInstance());
}
return items;
}
when you assign your list to a list variable you will have to cast it.
such as:
List<Student> students = (List<Student>) MyFunction(Student.class);
you can use a pattern stategy like this :
///interface
package strategy;
public interface IStrategy {
public void appliquerStrategy();
}
package tpdesignpattern2.strategy;
public class StrategyImpl1 implements IStrategy{
#Override
public void appliquerStrategy() {
System.out.println("Appliquer la strategy 1");
}
}
package tpdesignpattern2.strategy;
public class StrategyImpl2 implements IStrategy{
#Override
public void appliquerStrategy() {
System.out.println("Appliquer la strategy 2");
}
}
/////// Context class
package tpdesignpattern2.strategy;
public class Context {
/***
* injection de l'interface
*/
private IStrategy iStrategy = new StrategyImpl1() ;
/**
* #param iStrategy
*/
public void setiStrategy(IStrategy iStrategy) {
this.iStrategy = iStrategy;
}
public void appliquerStrategy() {
iStrategy.appliquerStrategy();
}
}
///Application
package tpdesignpattern2.strategy;
import java.util.Scanner;
import strategy.IStrategy;
public class App {
public static void main(String[] args) {
Context context = new Context();
Scanner scanner = new Scanner(System.in);
while(true) {
System.out.print("Entrer le nom de la calss : ");
String nom = "tpdesignpattern2.strategy."+scanner.nextLine();
tpdesignpattern2.strategy.IStrategy strategy;
try {
strategy = (tpdesignpattern2.strategy.IStrategy) Class.forName(nom).newInstance();
context.setiStrategy(strategy);
context.appliquerStrategy();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
};
}
}
}
Is there a better way (probably..) to build a class in which i can use set/get method.
Notice thay all the data are stock in a ArrayList.
public class PorterList
{
public PorterList()
{
ArrayList<Porter> porList = new ArrayList<>();
}
public PorterList(ArrayList<Porter> p)
{
ArrayList<Porter> porList = p;
}
SimpleDateFormat porterDF = new SimpleDateFormat("HH:mm:ss");
private Porter p = new Porter();
private int _porterNo;
public String getStatus(int porterNo)
{
_porterNo = porterNo;
p = porList.get(_porterNo);
return p.p_state;
}
There's something wrong on that second last line p = porList.get(_porterNo);
I want to use something like this in my main:
p_L = PorterList(p)
porter_status = p_L.get(5)
Thank you very much
Yor ArrayList is local variable and it's your problem. It's should be a field.
private ArrayList<Porter> porList;
public PorterList() {
porList = new ArrayList<>();
}
public PorterList(ArrayList<Porter> p
{
porList = p;
}
As you declare ArrayList porList = p; inside the constructors , It will become local variable , so it will not be visible outside that constructor , If you want it to use at your class level declare it at globally liek below
public class PorterList
{
private ArrayList<Porter> porList;
public PorterList()
{
porList = new ArrayList<>();
}
public PorterList(ArrayList<Porter> p)
{
porList = p;
}
}
In both of your constructors you have declared local variable porList - make this a field
public class PorterList
{
private ArrayList<Porter> porList;
public PorterList()
{
porList = new ArrayList<>();
}
public PorterList(ArrayList<Porter> p)
{
porList = p;
}
....
}
I'm trying to create a program which contains a generic method, which contains a type parameter. It should return an instance of the class Pair. I'm not sure how i can return a Pair. The code i have is below:
public class MinMaxArray
{
public static <ArrayType extends Comparable<ArrayType>>
ArrayType getMinMax(ArrayType[] anArray)
throws IllegalArgumentException
{
try
{
ArrayType resultMin = anArray[0];
ArrayType resultMax = anArray[0];
for (int index = 1; index < anArray.length; index++)
if (result.compareTo(anArray[index]) < 0)
result = anArray[index];
if (result.compareTo(anArray[index]) > 0)
result = anArray[index];
return resultMin;
return resultMax;
}//try
catch (ArrayIndexOutOfBoundsException e)
{ throw new IllegalArgumentException("Array must be non-empty", e); }
catch (NullPointerException e)
{ throw new IllegalArgumentException("Array must exist", e); }
}//getMinMax
}//class MinMaxArray
Pair class Code:
//Two onjects grouped into a pair.
public class Pair<FirstType, SecondType>
{
//The first object.
private final FirstType first;
//The second object.
private final SecondType second;
//Constructor is given the two objects.
public Pair(FirstType requiredFirst, SecondType requiredSecond)
{
first = requiredFirst;
second = requiredSecond;
}//Pair
//Return the first object.
public FirstType getFirst()
{
return first;
}//GetFirst
//Return the second object.
public SecondType getSecond()
{
return second;
}//GetSecond
}//class Pair
I'm not sure how i can get the resultMax and resultMin to return as a Pair. Thanks for the help.
Perhaps,
public static <ArrayType extends Comparable<ArrayType>>
Pair<ArrayType, ArrayType> getMinMax(ArrayType[] anArray) {
...
return new Pair<ArrayType, ArrayType>(resultMin, resultMax);
}
try
return new Pair<ArrayType, ArrayType>(resultMin, resultMax);
IMHO I would use
return new ArrayType[] { resultMin, resultMax };
or you could add a factory method to Pair class
public static <FirstType, SecondType> Pair<FirstType, SecondType> of(FirstType first, SecondType second) {
return new Pair<FirstType, SecondType>(first, second);
}
then you can write
return Pair.of(resultMin, resultMax);
I have been trying to verify if the ThreadLocal members are indeed different in different threads.
This is my TestClass whose object I am sharing among multiple threads.
public class TestClass {
private static Set<Integer> setI;
private static ThreadLocal<Set<String>> setS;
public TestClass() {
Set<String> temp = new HashSet<String>();
for (int i=0; i<=4; i++) {
setI.add(i);
temp.add(Integer.toString(i));
}
setS.set(temp);
}
static {
setI = new HashSet<Integer>();
setS = new ThreadLocal<Set<String>>() {
protected Set<String> initialValue() {
return new HashSet<String>();
}
};
}
public static void addToIntegerSet(int i) {
synchronized(setI) {
setI.add(i);
}
}
public static void addToStringSet(String str) {
Set<String> sets = setS.get();
sets.add(str);
setS.set(sets);
}
}
the following is the class I use to test this out :-
package personal;
import java.util.*;
import personal.TestClass;
import java.lang.reflect.Field;
public class Test2 {
private static TestClass testObj;
private static Set<Set<String>> testStringSet;
private static Set<Set<Integer>> testIntegerSet;
static {
testObj = new TestClass();
testStringSet = new HashSet<Set<String>>();
testIntegerSet = new HashSet<Set<Integer>>();
}
private static void addToStringSet(Set<String> sets) {
synchronized(testStringSet) {
testStringSet.add(sets);
}
}
private static void addToIntegerSet(Set<Integer> sets) {
synchronized(testIntegerSet) {
testIntegerSet.add(sets);
}
}
private static int getTestIntegerSetSize() {
synchronized(testIntegerSet) {
return testIntegerSet.size();
}
}
private static int getTestStringSetSize() {
synchronized(testStringSet) {
return testStringSet.size();
}
}
private static class MyRunnable implements Runnable {
private TestClass tc;
private String name;
public MyRunnable(TestClass tc, int i) {
this.name = "Thread:- " + Integer.toString(i);
this.tc = tc;
}
#Override
public void run() {
try {
Field f1 = tc.getClass().getDeclaredField("setS");
Field f2 = tc.getClass().getDeclaredField("setI");
f1.setAccessible(true);
f2.setAccessible(true);
Set<String> v1 = (Set<String>)(((ThreadLocal<Set<String>>)(f1.get(tc))).get());
Set<Integer> v2 = (Set<Integer>) f2.get(tc);
addToIntegerSet(v2);
addToStringSet(v1);
} catch (Exception exp) {
System.out.println(exp);
}
}
}
public static void main(String[] args) {
for (int i=1; i<=2; i++) {
(new Thread (new MyRunnable(testObj,i))).start();
}
try {
Thread.sleep(5);
} catch (Exception exp) {
System.out.println(exp);
}
System.out.println(getTestStringSetSize());
System.out.println(getTestIntegerSetSize());
}
}
thus the 1st print statement should print out 2 and the second one should print out 1.
how ever the 1st print statement also prints out 1.
what is wrong ?
For a test class, I'd start with something much, much simpler. Just store a String or something in the ThreadLocal to start with, and avoid the reflection calls (setAccessible, etc.). Your issue is most likely in all of this extra code, and nothing due to the ThreadLocal itself.