Our teacher asked us to make a method which takes a Class as a parameter then checks the fields and methods if they follow the rules of Checkstyle (Upper case, lower case, final attribute, etc.)
He gave us a piece of code to start with but I don't know what to do next.
public class CheckStyle {
static String valider(Class c){
Field[] tattribut = c.getDeclaredFields();
String name = c.getName();
Method[] tmethod=c.getDeclaredMethods();
}
public static void main(String[] args) {
String error = CheckStyle.valider(a.class);
System.out.println(error);
}
}
Try to use some of this code:
public class SomeClass {
private String aaa;
private String bbb;
private double ccc;
}
public static void main(String[] args){
List<Field> privateFields = new ArrayList<>();
Field[] allFields = SomeClass.class.getDeclaredFields();
for (Field field : allFields) {
if (Modifier.isPrivate(field.getModifiers())) {
privateFields.add(field);
}
}
}
Then go over your fields to see if they are in the correct format you need and ect.
Related
Lambda is used here, but when ::new is used, the following parameters are populated into the constructor:
#FunctionalInterface
interface Lambdademo1<T> {
T test(String s);
}
class Test {
public static void test2(Lambdademo1<Apple> lambdademo1, String s) {
Apple i = lambdademo1.test(s);
System.out.println(i.getColor());
}
public static void main(String args[]){
test2(Apple::new,"hehehe");
}
}
Output:
hehehe
UPDATE:
class test {
public static void main(String args[]) {
test1((String s) -> new Integer(1), "hehehe");
test1(Integer::new, "hehehe"); //It's wrong
test2(Apple::new,"hehehe");
test3(Apple1::new,"hehehe"); //Compile error
// I think XXX::new is equivalen to new XXX() but here shoe it's not
}
public static void test1(Lambdademo1<Integer> lambdademo1, String s) {
Integer i = lambdademo1.test(s);
System.out.println(i);
}
public static void test2(Lambdademo1<Apple> lambdademo1, String s) {
Apple i = lambdademo1.test(s);
System.out.println(i.getColor());
}
public static void test3(Lambdademo1<Apple1> lambdademo1, String s) {
Apple1 i = lambdademo1.test(s);
System.out.println(i.getColor());
}
}
The Apple1 class:
class Apple1 {
private String color;
// getter and setter
}
The Apple class:
class Apple {
private String color;
public Apple(String color) {
this.color = color;
}
// getter and setter
}
Original answer
Apple::new can (and does) refer to a constructor Apple(String) because it follows the contract of T test(String s) - (String string) -> new Apple(string); or Apple:new
Apparently, that constructor sets the value for the color field since the getter returns the value you passed to the constructor.
test2(Apple::new,"hehehe");
is equivalent to
System.out.println(new Apple("hehehe").getColor());
Update
Let's discuss each line in detail to make it clear.
1.
test1((String s) -> new Integer(1), "hehehe");
You are taking a String s, not using it, and returning a constant new Integer(1) or simply 1.
We might rewrite it to
test1(s -> 1,"hehehe" );
2.
test1(Integer::new, "hehehe");
It's not wrong. It's absolutely compilable line. There is a constructor Integer(String s) that converts the given String to an int using Integer.parseInt(String).
Since "hehehe" isn't a parsable int, you will get a NumberFormatException, but that's a runtime issue.
3.
It's fine, and I have explained it in the original answer above.
4.
test3(Apple1::new,"hehehe");
You haven't defined any constructors for Apple1, so we have the no-arguments one by default. Since it doesn't take a String, we can't use it to represent Lambdademo1#test.
Writing a lambda will make it compile, though.
test3(s -> new Apple1(),"hehehe");
I think XXX::new is equivalent to new XXX() but here it's not.
It depends on context. XXX::new always refers to a constructor. What constructor? We don't know it until we see the context.
Examine an example where Apple::new points at 3 different constructors.
class Apple {
public Apple() {}
public Apple(Integer i) {}
public Apple(String s) {}
public static void main(String[] args) {
Supplier<Apple> a = Apple::new;
Function<Integer, Apple> b = Apple::new;
Function<String, Apple> c = Apple::new;
}
}
I have a class with this, it's an example code, not the real code
private static String className;
public static Wish getInstance(Class<?> clazz) {
if(wish == null)
wish = new Wish();
className = clazz.getName();
return wish;
}
Many classes use this Wish class, then each class should "say" a wish with the className passed in the getInstance method.
Then I have something like this
public class Boy {
private Wish w = Wish.getInstance(Boy.class);
//at this moment the static variable take "com.package.Boy" value
....
}
Another classs
public class Girl {
private Wish w = Wish.getInstance(Girl.class);
//at this moment the static variable take "com.package.Girl" value
....
}
When everybody start to say their wishes, example
public class WishesDay {
private Girl g;
private Boy b;
public void makeYourWish() {
g = new Girl(); //get the com.package.Girl value
b = new Boy(); //get the com.package.Boy value
//sample output "com.package.Boy wants A pink house!"
g.iWish("A pink house!"); // the boys don't want this things :(
b.iWish("A spatial boat!");
}
}
I know that each object have the same copy o the Wish class and the static variable className change when each object (Girl, Boy) call the Wish.getInstance(Class<?> clazz) method.
How can I use a static variable (I want avoid to instantiate the Wish class) and keep the correct value for the variable className.
Can I make this with a static variable? or the solution is to instantiate (no static variable)
For example, log4j has the Logger class, I want to make the same thing with the class name.
You'll have to make your constructor private if you want to avoid instantiate the Wish class and make the className not static.
public class Wish {
String className;
private Wish(String className){
this.className = className;
}
public static Wish getInstance(Class<?> clazz) {
String className = clazz.getName();
return new Wish(className);
}
public String getClassName() {
return className;
}
}
package com.test;
public class WishesDay {
private Girl g;
private Boy b;
public void makeYourWish() {
g = new Girl(); //get the com.package.Girl value
b = new Boy(); //get the com.package.Boy value
//sample output "com.package.Boy wants A pink house!"
g.iWish("A pink house!"); // the boys don't want this things :(
b.iWish("A spatial boat!");
}
public static void main(String[] args) {
WishesDay wd = new WishesDay();
wd.makeYourWish();
//outputs com.test.Girl wants A pink house!
//com.test.Boy wants A spatial boat!
}
}
Example
class MyClass {
String name;
String NAme;
public static void main(String args[]) {
}
}
Output should be:
name is in standard form
NAme is not in standard form
Its possible through reflection.You can get all the declared fields using:-
public static void main(String args[]) {
Field[] fields = MyClass.class.getDeclaredFields();
for(Field field : fields ){
field.setAccessible(true);
String name = field.getName();
//Check if name contains small letters or the logic to check if camel-case etc
}
}
You cannot do this for local variables
I am creating a helper class in parsing XML elements, so the developer do not need to know the exact name and capitalization of the XML fields.
private static class TagNames{
public static String RESOURCE_ID = "ResourceId";
public static String RESOURCE_NAME = "ResourceName";
public static String RESOURCE_PRICE = "ResourcePrice";
}
This makes it easier to do things like:
someXMLParser.getValueByTagName(TagNames.RESOURCE_ID);
My question is this. If I want to iterate over all the fields declared in class TagNames, how do I do that? Pseudocode:
For tag in TagNames:
someXMLParser.getValueByTagName(tag)
I know I will probably have to restructure all of this. But I can't figure out a way to make the names easily accessible as well as iterable, without any duplication.
Any suggestions?
You're literally asking for a solution based on reflection, but I think a Java Enum may be a better choice in this case. Building on Frederick's example:
public class EnumTest {
public enum Tags {
RESOURCE_ID("ResourceId"),
REOURCE_NAME("ResourceName"),
RESOURCE_PRICE("ResourcePrice");
private final String tagName;
Tags(String tagName) {
this.tagName = tagName;
}
public String getTagName() {
return tagName;
}
}
public static void main(String[] args) {
for(Tags tag : Tags.values()) {
System.out.println("const:" + tag.name()
+ " tagName:" + tag.getTagName());
}
// API user might do e.g.:
// document.getValueForTag(Tags.REOURCE_NAME);
}
}
Although I agree that you should probably use enums or ResourceBundles, here's a solution to your actual question. A method that generates a Map name -> value from all public constants in a given class (the only thing that's missing should be try / catch or throws)
public static Map<String, Object> getConstantValues(Class<?> clazz){
Map<String, Object> constantValues = new LinkedHashMap<String, Object>();
for(Field field : clazz.getDeclaredFields()){
int modifiers = field.getModifiers();
if(Modifiers.isPublic(mod)
&& Modifiers.isStatic(mod) && Modifiers.isFinal(mod)){
constantValues.put(field.getName(), field.get(null));
}
}
return constantValues;
}
You may want to consider using a ResourceBundle instead of a class to store the tag names. May require a little bit of reworking of your code but it will be easier to produce a list of tags compared to what you are doing now, and adding a new tag won't require much work other then adding a line to the properties file.
You can do this quite easily using enum and an accompanying array:
public class Main {
public enum TagName { RESOURCE_ID, REOURCE_NAME, RESOURCE_PRICE }
private static String[] tags = {"ResourceID", "ResourceName", "ResourcePrice"};
public static String getValueByTagName(TagName tag) {
return tags[tag.ordinal()];
}
public static void main(String[] args) {
System.out.println("Calling by getValueByTagName:");
System.out.println(getValueByTagName(TagName.RESOURCE_ID));
System.out.println("Calling TagName.values() for loop:");
for (TagName t : TagName.values()) {
System.out.println(getValueByTagName(t));
}
}
}
Using an enum is a good fit, especially if you use a custom constructor and the built in "values" method:
public class Main {
public static enum TagName {
RESOURCE_ID("ResourceId"),
RESOURCE_NAME("ResourceName"),
RESOURCE_PRICE("ResourcePrice"),
;
private String s;
private TagName(String s) { this.s = s; }
public String toString() { return this.s; }
public static String[] strings() {
List<String> ss = new ArrayList<String>();
for (TagName tagName : TagName.values()) {
ss.add(tagName.toString());
}
return ss.toArray(new String[ss.size()]);
}
}
public static void main(String[] args) {
// Use TagName.values() for the enums, or for strings...
for (String s : TagName.strings()) {
System.out.println(s);
}
}
}
This way you can simply add new tags and they'll automatically get picked up by the "strings" method; for extra performance you could compute that string array just once, statically, since you can't change the set of enums dynamically. You could get even fancier by auto-generating the tag strings from their constant values, if they are really normalized...
I have the folowing interface;
public static interface Attributes
{
public final static String InterestDeterminationDate = "InterestDeterminationDate";
public final static String CreditType = "CreditType";
public final static String NumberInternal = "NumberInternal";
public final static String InterestRate = "InterestRate";
public final static String RemainingDebtAmount = "RemainingDebtAmount";
public final static String ConsumerPart = "ConsumerPart";
public final static String TechnicalProductName = "TechnicalProductName";
public final static String TermOfDuration = "TermOfDuration";
public final static String PeriodInterestTaxReduction = "PeriodInterestTaxReduction";
public final static String OriginMark = "OriginMark";
public final static String Currency = "Currency";
public final static String PenaltyRuleId = "PenaltyRuleId";
public final static String InstallmentCalculationMethod = "InstallmentCalculationMethod";
public final static String InterestRenewalDate = "InterestRenewalDate";
public final static String TechnicalProductDescription = "TechnicalProductDescription";
public final static String TechnicalProductDate = "TechnicalProductDate";
public final static String CollectionIntervalPeriod = "CollectionIntervalPeriod";
public final static String Enddate = "Enddate";
}
I need to check is a given string is a part of this Attributes Interface.
How can i check this?
Regards,
bas Hendriks
If you really want todo this, then you should use reflection and go through all the values in Attributes.
A better way to do this would be the use of enums :
public enum Attributes{
InterestDeterminationDate,
CreditType,
NumberInternal,
InterestRate,
RemainingDebtAmount,
ConsumerPart,
TechnicalProductName,
TermOfDuration,
PeriodInterestTaxReduction,
OriginMark,
Currency,
PenaltyRuleId,
InstallmentCalculationMethod,
InterestRenewalDate,
TechnicalProductDescription,
TechnicalProductDate,
CollectionIntervalPeriod,
Enddate;
}
and the Attributes.valueOf(yourVariable); would check this for you.
Beware with enum, the valueOf() method will throw a IllegalArgumentException if yourVariable isn't in Attributes. Plus you yourVariable isn't null or you will have to handle a NullPointerException
Your question doesn't make it clear whether you're trying to find out if the query string is the property name or value. If you're trying to find out if it's a value, the following will work:
public static boolean hasValue(String value) throws IllegalAccessException {
for(Field field : Attributes.class.getDeclaredFields()) {
if(((String)field.get(Attributes.class)).equals(value)) {
return true;
}
}
return false;
}
However, I would advise following Colin's suggestion of using an Enum, it will be easier for you to work with in the future.
You can build a set using reflection and test against that set:
Class<Attributes> attr = Attributes.class;
Field[] fields = attr.getDeclaredFields();
final Set<String> fieldsInAttributes = new HashSet<String>();
for (Field field : fields) {
fieldsInAttributes.add(field.getName());
}
System.out.println(fieldsInAttributes.contains("PenaltyRuleId"));
You can use the reflection API, and the "getFields()" method of the Class class.
Then you check the field name with the "getName()" method of the Field class.
Here is the Oracle official tutorial.
public static String getFieldName(String fieldValue) throws Exception {
for (Field field : Attributes.class.getFields())
if (fieldValue.equals(field.get(null)))
return field.getName();
return null;
}