I'm trying to compare two objects of the same type (in method doesHave), but I've never got "true" returned. Here's my code:
private ArrayList<Osoba> osoba = new ArrayList<Osoba>();
public boolean doesHave(Osoba o) {
for (int i = 0; i < osoba.size(); i++) {
if (pobierz(i).equals(o))
return true;
}
return false;
}
public Osoba pobierz(int index) {
return osoba.get(index);
}
The 'Osoba' class, looks like this:
public class Osoba {
private String imie;
private String nazwisko;
public String toString() {
return imie + " " + nazwisko;
}
public Osoba(String name, String surname) {
imie = name;
nazwisko = surname;
}
public String getImie() {
return imie;
}
public String getNazwisko() {
return nazwisko;
}
}
Code from main:
Osoba osoby = new Osoba(name, surname);
if (kartoteka.doesHave(osoby) == Boolean.TRUE) {
temp = odczyt.nextLine();
if (temp.equals("y"))
kartoteka.usun(osoby); //some method
else
...
}
No matter what input I'd use, this part never happens.
'kartoteka' is my package which of course I have imported. Each class is in separate package, but there is no problem with using them. I've tried googling it for quite some time, but nothing helped me, it just seems like
if (kartoteka.doesHave(osoby) == Boolean.TRUE)
Is never true, but I have no idea why. Code without Boolean.TRUE doesn't work as well. If I could get some hints, I'd be thankful. Sorry for asking that kind of question, but I'm new in java.
Imagine that you and your wife have twins.
Are they the "same" person? No, they are not. Lets call them twin A and twin B. They are two different instances, yes, they look same, but if you are talking twin A, you are not talking about twin B and vice versa. The point is, they are not EQUAL :), it is same in Java. Twin A is equal only to itself, no1 else.
You have to create your own method, which compares all properties of two instances of Osoba.
The other option is to override the equals and hashCode methods, but it is not good approach in your case.
Right now your code checks if the memory address of two objects is the same which can only be true if it is the same exact object.
You need to implement a method that compares two Osoba objects by comparing whichever properties you want from these objects and returning true/false appropriately.
Osaba should implement equals:
#Override
public boolean equals(Object other) {
return imie.equals(((Osaba) other).getImie())
&& nazwisko.equals(((Osaba) other).getNazwisko()));
}
If you do not implement equals, the default implementation will be used.
Responds from #libik and #Code Whisperer helped me, so if anyone has the same problem, read and try to understand, it helped for me. I like that twins allegory :) It's kind of the same situation when I tried to compare two Strings.
Related
I'm having an argument with my friend and I would like to know your opinion.
In a test do you think that is better to compare field by field or just create a expectedResultObject and compare it.
For instance:
Assert.That(obj.Foo).isEqualTo(FOO);
Assert.That(obj.Test).isEqualTo(TEST);
vs
Foo expected = new Foo(FOO, TEST);
assertThat(obj).usingRecursiveComparison().isEqualTo(expected);
In this example we only have two fields but we can have allot more.
Thanks
If you can have multiple fields, the expected method is better because you'll be adding the other fields inside the constructors' params. Imagine if you have 100 fields, adding them line by line as you suggested in your first example would be a headache, while adding in the params would be a bit simpler.
Between the two possibilities, I prefer the one without the usingRecursiveComparison().
I wanted to add a few thins :
An object is not a data toolbox, so it's not a good thing to add getter/setter to test your object's creation. It's better test a behaviour, a method where you can test the return.
Generally I'm not fond of writing more than one assertion in a test.
There is a technique which made assertions more lisibles (with AssertJ but I think you can make this kind of thing with Hamcrest).
The initial class :
public class Amount {
private int value;
public Integer add(int amountToAdd) {
value += amountToAdd;
return value;
}
}
Create an Asserter :
public class IntegerAsserter extends org.assertj.core.api.AbstractAssert<IntegerAsserter, Integer> {
IntegerAsserter(Integer actual) {
super(IntegerAsserter.class, actual);
}
public IntegerAsserter isBetweenOneOrTwo() {
Assert.assertTrue(actual < 2);
Assert.assertTrue(actual > 1);
return this;
}
}
Create a new Assertions :
public class Assertions extends org.fest.assertions.Assertions {
public static IntegerAsserter assertThat(Integer actual) {
return new IntegerAsserter(actual);
}
}
And then use it :
public void should_be_between_one_or_two {
Amount amount = new Amount(0);
Integer newAmount = amount.add(1);
Assertions.assertThat(obj).isBetweenOneOrTwo();
}
I am currently working on a project where I want to implement a login mechanism using a username and a password that gets compared against a database.
I had something like this in mind:
public boolean verifyUser( String username, char[] password )
{
List<char[]> dbpass = getPasswords( username );
if ( dbpass.contains( password ) )
{
overwriteWithNonsense( password );
return true;
}
overwriteWithNonsense( password );
return false;
}
when I noticed that my unit tests were failing. So I took a deeper look at it an noticed that the Object::equals method is not overriden for arrays of primitives which explained why List::contains would always evaluate to false.
I know there is a possible workaround using:
if ( dbpass.stream().anyMatch( pw -> Arrays.equals( pw, password ) ) )
{
overwriteWithNonsense( password );
return true;
}
My question is why the designer chose to keep the 'default implementation' of Object::equals? Wouldn't it be way more convenient than implementing a framework with static utility methods like Arrays.equals(array1,array2)?
Any Collections of arrays is mostly bad design. They should not be used together. You're probably better of by introducing a trivial, but needed class:
public class Password{
private final char[] password;
public Password(char[] password){
this.password = password;
}
#Override
public boolean equals(Object obj){
// equals logic
}
#Override
public int hashCode(){
// hashCode logic
}
}
And then having a List<Password>. (I also shortened your verifyUser method because it seemed a bit redundant):
public boolean verifyUser( String username, char[] password ){
List<Password> dbpass = getPasswords(username);
boolean contained = dbpass.contains(new Password(password));
overwriteWithNonsense(password);
return contained;
}
(Your other question regarding the why it is not overriden is mostly off-topic, because only the java-devs could really answer that.)
In Java array is not a class but from Java Doc section 4.3.1 it is treated as an object. Now as this is not a class there's no code for equals/hashCode.
Now, for your solution to compare arrays you can use Arrays.equals method to compare two arrays:
public boolean verifyUser( String username, char[] password )
{
List<char[]> dbpass = getPasswords( username );
for(char[] arr : dbpass)
{
if ( Arrays.equals(arr,password) )
{
overwriteWithNonsense( password );
return true;
}
}
overwriteWithNonsense( password );
return false;
}
I don't think there is a good reason. You're generally encouraged to use ArrayList as its a fully-fledged container. But there seems only good to be had by implementing equals() as per AbstractList.
There's always == to determine if two references are the same object.
Java arrays are a bit of an unusual beast in that they might contain primitives but that doesn't seem too much of a hurdle.
Are these arrays equal?
Integer objects[]={Integer.valueOf(1),Integer.valueOf(1000)};
int integers[]={1,1000};
I'd go with 'no' as most consistent. But if not you will get the potentially surprise semantics that these objects won't be equal:
int ai[]={1,2,3};
long al[]={1,2,3};
Perhaps no one really thought about it and changing something so basic like that will surely have some code-breaking consequences.
I'm trying to display Car from fleet ArrayList using user input. Unfortunately I'm not sure how to go about it. I have found few examples online but cannot make them work. I have incorporated following method:
void findRegNo(String reg){
boolean exist=false;
for(int i=0;i<this.fleet.size();i++){
if(this.fleet.get(i).getRegNo() == reg){
exist=true;
break;
}
}
if(exist) {
System.out.println("!!!!!");
} else {
System.out.println("xxx");
}
}
At the moment the result is always: xxx so the code does not find any match. That function is placed in my container class, I was thinking that maybe it supposed to be in different location.
These are variables of Car class:
public class Car {
//defining variables
String regNo;
String model;
double mileage;
Strings are objects, not primitives. Hence, you should use equals to compare their value, not ==, which checks that both references are to the same object:
if (this.fleet.get(i).getRegNo().equals(reg)) {
exist = true;
break;
}
Most people understand the innate benefits that enum brings into a program verses the use of int or String. See here and here if you don't know. Anyway, I came across a problem that I wanted to solve that kind of is on the same playing field as using int or String to represent a constant instead of using an enum. This deals specifically with String.format(...).
With String.format, there seems to be a large opening for programmatic error that isn't found at compile-time. This can make fixing errors more complex and / or take longer.
This was the issue for me that I set out to fix (or hack a solution). I came close, but I am not close enough. For this problem, this is more certainly over-engineered. I understand that, but I just want to find a good compile-time solution to this, that provides the least amount of boiler-plate code.
I was writing some non-production code just to write code with the following rules.
Abstraction was key.
Readability was very important
Yet the simplest way to the above was preferred.
I am running on...
Java 7 / JDK 1.7
Android Studio 0.8.2
These are unsatisfactory
Is there a typesafe alternative to String.format(...)
How to get string.format to complain at compile time
My Solution
My solution uses the same idea that enums do. You should use enum types any time you need to represent a fixed set of constants...data sets where you know all possible values at compile time(docs.oracle.com). The first argument in String.format seems to fit that bill. You know the whole string beforehand, and you can split it up into several parts (or just one), so it can be represented as a fixed set of "constants".
By the way, my project is a simple calculator that you probably seen online already - 2 input numbers, 1 result, and 4 buttons (+, -, ×, and ÷). I also have a second duplicate calculator that has only 1 input number, but everything else is the same
Enum - Expression.java & DogeExpression.java
public enum Expression implements IExpression {
Number1 ("%s"),
Operator (" %s "),
Number2 ("%s"),
Result (" = %s");
protected String defaultFormat;
protected String updatedString = "";
private Expression(String format) { this.defaultFormat = format; }
// I think implementing this in ever enum is a necessary evil. Could use a switch statement instead. But it would be nice to have a default update method that you could overload if needed. Just wish the variables could be hidden.
public <T> boolean update(T value) {
String replaceValue
= this.equals(Expression.Operator)
? value.toString()
: Number.parse(value.toString()).toString();
this.updatedString = this.defaultFormat.replace("%s", replaceValue);
return true;
}
}
...and...
public enum DogeExpression implements IExpression {
Total ("Wow. Such Calculation. %s");
// Same general code as public enum Expression
}
Current Issue
IExpression.java - This is a HUGE issue. Without this fixed, my solution cannot work!!
public interface IExpression {
public <T> boolean update(T Value);
class Update { // I cannot have static methods in interfaces in Java 7. Workaround
public static String print() {
String replacedString = "";
// for (Expression expression : Expression.values()) { // ISSUE!! Switch to this for Expression
for (DogeExpression expression : DogeExpression.values()) {
replacedString += expression.updatedString;
}
return replacedString;
}
}
}
So Why Is This An Issues
With IExpression.java, this had to hacked to work with Java 7. I feel that Java 8 would have played a lot nicer with me. However, the issue I am having is paramount to getting my current implementation working The issue is that IExpression does not know which enum to iterate through. So I have to comment / uncomment code to get it to work now.
How can I fix the above issue??
How about something like this:
public enum Operator {
addition("+"),
subtraction("-"),
multiplication("x"),
division("÷");
private final String expressed;
private Operator(String expressed) { this.expressed = expressed; }
public String expressedAs() { return this.expressed; }
}
public class ExpressionBuilder {
private Number n1;
private Number n2;
private Operator o1;
private Number r;
public void setN1(Number n1) { this.n1 = n1; }
public void setN2(Number n2) { this.n2 = n2; }
public void setO1(Operator o1) { this.o1 = o1; }
public void setR(Number r) { this.r = r; }
public String build() {
final StringBuilder sb = new StringBuilder();
sb.append(format(n1));
sb.append(o1.expressedAs());
sb.append(format(n2));
sb.append(" = ");
sb.append(format(r));
return sb.toString();
}
private String format(Number n) {
return n.toString(); // Could use java.text.NumberFormat
}
}
I am trying to create a new BST from the intersection of 2 known BSTs. I am getting a NullPointerException in the intersect2 method int he second case, at the line "cur3.item.set_account_id(cur1.item.get_accountid()+ cur2.item.get_accountid());". I know you get the error when you try to dereference the variable without initializing it but i think i am initializing it? I'm not really sure. I would appreciate the help.
public static Bst<Customer> intersect(Bst<Customer> a, Bst<Customer> b){
return( intersect2(a.root, b.root));
}
public static Bst<Customer> intersect2(BTNode<Customer> cur1, BTNode<Customer> cur2){
Bst<Customer> result = new Bst<Customer>();
// 1. both empty -> true
if (cur1==null && cur2==null){
result=null;
}
// 2. both non-empty -> compare them
else if (cur1!=null && cur2!=null) {
BTNode<Customer> cur3 = new BTNode<Customer>();
cur3.item.set_account_id(cur1.item.get_accountid()+ cur2.item.get_accountid());
result.insert(cur3.item);
intersect2(cur1.left, cur2.left);
intersect2(cur1.right, cur2.right);
}
// 3. one empty, one not -> false
else if (cur1==null ||cur2==null){
BTNode<Customer> cur3 = new BTNode<Customer>();
cur3.item=null;
intersect2(cur1.left, cur2.left);
intersect2(cur1.right, cur2.right);
}
return result;
}
Here is the image of the problem:
A NullPointerException can be caused by a number of things. In your given example, cur1 and cur2 are not null, but there is no guarantee that cur1.item, cur1.item.accountId (and similarly for cur2) are not null.
Being as you have no description for the underlying implementation, I cannot assist further.
I can suggest that you do some of a few things:
1.) check the implementation of your objects (if this happens EVERY time, there may be some sort of initialization problem.
2.) Whenever you create an instance of your item, do you make sure to specify the accountId field? Try giving a default value for this field so it cannot be null. (try some sort of illegal value [eg -1, false, etc] and test for it.
If you would post more implementation details, I (or someone) may be able to directly identify the problem.
Regards.
Edit:4/20#17:11
Here's an example of what you should be doing.
public class Customer {
private int accountId;
public Customer() {
this.accountId = 0;
}
public Customer(int account_identification) {
this.accountId = account_identification);
}
//As a side note, general practice implies fields be private
//Use a method (hence the term 'getter' and the reciprocal, 'setter')
public int getId() {
return this.accountId;
}
public void setId(int replacement_account_identification) {
this.accountId = replacement_account_identification;
}
}
It is because the item variable in Customer object is not initialized.
Does creating a BTNode automatically allocate its member item ?
You do:
cur3.item.set_account_id(.. )
For this to succeed, both cur3 and cur3.item need to be not null.
Same applies to cur1 and cur2 as well, that you reference later in that line.
And the example of the 3rd case shows that BTNode.item can be null in some scenarios:
cur3.item=null;