Priorities.NORMAL_PRIORITY).addClass(this);
obj.isAbstract() ? Priorities.LOW_PRIORITY : Priorities.NORMAL_PRIORITY).addClass(this);
	public void visitAfter(JavaClass obj) {		if (!obj.isClass())			return;		if (getDottedClassName().equals("java.lang.Object"))			return;		int accessFlags = obj.getAccessFlags();		if ((accessFlags & ACC_INTERFACE) != 0)			return;		visibleOutsidePackage = obj.isPublic() || obj.isProtected();				String whereEqual = getDottedClassName();		boolean classThatDefinesEqualsIsAbstract = false;		boolean classThatDefinesHashCodeIsAbstract = false;		boolean inheritedHashCodeIsFinal = false;		boolean inheritedEqualsIsFinal = false;		boolean inheritedEqualsIsAbstract = false;		if (!hasEqualsObject) {			JavaClass we = Lookup.findSuperImplementor(obj, "equals",					"(Ljava/lang/Object;)Z", bugReporter);			if (we == null) {				whereEqual = "java.lang.Object";			} else {				whereEqual = we.getClassName();				classThatDefinesEqualsIsAbstract = we.isAbstract();				Method m = findMethod(we, "equals", "(Ljava/lang/Object;)Z");				if (m != null && m.isFinal())					inheritedEqualsIsFinal = true;				if (m != null && m.isAbstract())					inheritedEqualsIsAbstract = true;			}		}		boolean usesDefaultEquals = whereEqual.equals("java.lang.Object");		String whereHashCode = getDottedClassName();		if (!hasHashCode) {			JavaClass wh = Lookup.findSuperImplementor(obj, "hashCode", "()I",					bugReporter);			if (wh == null) {				whereHashCode = "java.lang.Object";			} else {				whereHashCode = wh.getClassName();				classThatDefinesHashCodeIsAbstract = wh.isAbstract();				Method m = findMethod(wh, "hashCode", "()I");				if (m != null && m.isFinal())					inheritedHashCodeIsFinal = true;			}		}		boolean usesDefaultHashCode = whereHashCode.equals("java.lang.Object");		if (false && (usesDefaultEquals || usesDefaultHashCode)) {			try {				if (Repository.implementationOf(obj, "java/util/Set")						|| Repository.implementationOf(obj, "java/util/List")						|| Repository.implementationOf(obj, "java/util/Map")) {					// System.out.println(getDottedClassName() + " uses default					// hashCode or equals");				}			} catch (ClassNotFoundException e) {				// e.printStackTrace();			}		}		if (!hasEqualsObject && hasEqualsSelf) {			if (usesDefaultEquals) {				int priority = HIGH_PRIORITY;				if (usesDefaultHashCode || obj.isAbstract())					priority++;				if (!visibleOutsidePackage)					priority++;				BugInstance bug = new BugInstance(this, "EQ_SELF_USE_OBJECT",						priority).addClass(getDottedClassName());				if (equalsMethod != null)					bug.addMethod(equalsMethod);				bugReporter.reportBug(bug);			} else {				int priority = NORMAL_PRIORITY;				if (hasFields)					priority--;				if (obj.isAbstract())					priority++;				BugInstance bug = new BugInstance(this, "EQ_SELF_NO_OBJECT",						priority).addClass(getDottedClassName());				if (equalsMethod != null)					bug.addMethod(equalsMethod);				bugReporter.reportBug(bug);			}		}		//		 System.out.println("Class " + getDottedClassName());//		  System.out.println("usesDefaultEquals: " + usesDefaultEquals);//		  System.out.println("hasHashCode: : " + hasHashCode);//		  System.out.println("usesDefaultHashCode: " + usesDefaultHashCode);//		  System.out.println("hasEquals: : " + hasEqualsObject);//		  System.out.println("hasCompareToObject: : " + hasCompareToObject);//		  System.out.println("hasCompareToSelf: : " + hasCompareToSelf);		 		if ((hasCompareToObject || hasCompareToSelf) && usesDefaultEquals) {			BugInstance bug = new BugInstance(this, "EQ_COMPARETO_USE_OBJECT_EQUALS",					Priorities.NORMAL_PRIORITY).addClass(this);			if (compareToSelfMethod != null) bug.addMethod(compareToSelfMethod);			else bug.addMethod(compareToObjectMethod);			bugReporter.reportBug(bug);		}		if (!hasCompareToObject && hasCompareToSelf) {			if (!extendsObject)				bugReporter.reportBug(new BugInstance(this,						"CO_SELF_NO_OBJECT", NORMAL_PRIORITY).addClass(						getDottedClassName()).addMethod(compareToMethod));		}		// if (!hasFields) return;		if (hasHashCode && !hashCodeIsAbstract				&& !(hasEqualsObject || hasEqualsSelf)) {			int priority = LOW_PRIORITY;			if (usesDefaultEquals)				bugReporter.reportBug(new BugInstance(this,						"HE_HASHCODE_USE_OBJECT_EQUALS", priority).addClass(						getDottedClassName()).addMethod(hashCodeMethod));			else if (!inheritedEqualsIsFinal)				bugReporter.reportBug(new BugInstance(this,						"HE_HASHCODE_NO_EQUALS", priority).addClass(						getDottedClassName()).addMethod(hashCodeMethod));		}		if (!hasHashCode				&& (hasEqualsObject && !equalsObjectIsAbstract || hasEqualsSelf)) {			if (usesDefaultHashCode) {				int priority = HIGH_PRIORITY;				if (equalsMethodIsInstanceOfEquals)					priority += 2;				else if (obj.isAbstract() || !hasEqualsObject)					priority++;				if (priority == HIGH_PRIORITY)					nonHashableClasses.add(getDottedClassName());				if (!visibleOutsidePackage) {					priority++;				}				BugInstance bug = new BugInstance(this,						"HE_EQUALS_USE_HASHCODE", priority)						.addClass(getDottedClassName());				if (equalsMethod != null)					bug.addMethod(equalsMethod);				bugReporter.reportBug(bug);			} else if (!inheritedHashCodeIsFinal					&& !whereHashCode.startsWith("java.util.Abstract")) {				int priority = LOW_PRIORITY;				if (hasEqualsObject && inheritedEqualsIsAbstract)					priority++;				if (hasFields)					priority--;				if (equalsMethodIsInstanceOfEquals || !hasEqualsObject)					priority += 2;				else if (obj.isAbstract())					priority++;				BugInstance bug = new BugInstance(this,						"HE_EQUALS_NO_HASHCODE", priority)						.addClass(getDottedClassName());				if (equalsMethod != null)					bug.addMethod(equalsMethod);				bugReporter.reportBug(bug);			}		}		if (!hasHashCode && !hasEqualsObject && !hasEqualsSelf				&& !usesDefaultEquals && usesDefaultHashCode				&& !obj.isAbstract() && classThatDefinesEqualsIsAbstract) {			BugInstance bug = new BugInstance(this,					"HE_INHERITS_EQUALS_USE_HASHCODE", NORMAL_PRIORITY)					.addClass(getDottedClassName());			if (equalsMethod != null)				bug.addMethod(equalsMethod);			bugReporter.reportBug(bug);		}	}