Extend class without adding any new fields












2














Say we have a class like this:



class Bar {
boolean b;
}

class Foo {
String zoo;
Bar bar;
}


and then we have a class that extends Foo:



class Stew extends Foo {
public Stew(Bar b, String z){
this.bar = b;
this.zoo = z;
}
}


my question is - is there any way to prevent Stew from having any non-method fields that aren't in Foo? In other words, I don't want Stew to have any fields, I just want Stew to implement a constructor and maybe a method or two.



Perhaps there is an annotation I can use, that can do this?



Something like:



@OnlyAddsMethods
class Stew extends Foo {
public Stew(Bar b, String z){
this.bar = b;
this.zoo = z;
}
}


purpose - I am going to serialize Stew to JSON, but I don't want Stew to have any new fields. I want to let any developer working on this file to know that any additional fields will be ignored (or won't be recognized) etc.










share|improve this question




















  • 2




    At compile time? At runtime? Why do you consider fields a problem that needs preventing?
    – meriton
    Nov 21 at 1:03










  • The question would be why do you need Stew to extend Foo and prior to that why do you need bar and zoo in Foo? You can always choose to have a constructor which doesn't need to initialize the properties of parent class. Is that what you're looking for?
    – nullpointer
    Nov 21 at 1:03






  • 1




    If you go the annotation route, you can create an annotation processor that emits errors if you declare any fields inside a class with the corresponding annotation. This would happen during compilation.
    – Slaw
    Nov 21 at 1:06








  • 1




    @AlexanderMills I got the problem statement, just wanted to mark question-related. Also, why in such case is Stew even extending Foo from a design perspective?
    – nullpointer
    Nov 21 at 1:17








  • 1




    @AlexanderMills No, I don't. You could have generated the provided constructor in Foo itself. If that's not possible, I would have rather tried to solve that first.
    – nullpointer
    Nov 21 at 1:20
















2














Say we have a class like this:



class Bar {
boolean b;
}

class Foo {
String zoo;
Bar bar;
}


and then we have a class that extends Foo:



class Stew extends Foo {
public Stew(Bar b, String z){
this.bar = b;
this.zoo = z;
}
}


my question is - is there any way to prevent Stew from having any non-method fields that aren't in Foo? In other words, I don't want Stew to have any fields, I just want Stew to implement a constructor and maybe a method or two.



Perhaps there is an annotation I can use, that can do this?



Something like:



@OnlyAddsMethods
class Stew extends Foo {
public Stew(Bar b, String z){
this.bar = b;
this.zoo = z;
}
}


purpose - I am going to serialize Stew to JSON, but I don't want Stew to have any new fields. I want to let any developer working on this file to know that any additional fields will be ignored (or won't be recognized) etc.










share|improve this question




















  • 2




    At compile time? At runtime? Why do you consider fields a problem that needs preventing?
    – meriton
    Nov 21 at 1:03










  • The question would be why do you need Stew to extend Foo and prior to that why do you need bar and zoo in Foo? You can always choose to have a constructor which doesn't need to initialize the properties of parent class. Is that what you're looking for?
    – nullpointer
    Nov 21 at 1:03






  • 1




    If you go the annotation route, you can create an annotation processor that emits errors if you declare any fields inside a class with the corresponding annotation. This would happen during compilation.
    – Slaw
    Nov 21 at 1:06








  • 1




    @AlexanderMills I got the problem statement, just wanted to mark question-related. Also, why in such case is Stew even extending Foo from a design perspective?
    – nullpointer
    Nov 21 at 1:17








  • 1




    @AlexanderMills No, I don't. You could have generated the provided constructor in Foo itself. If that's not possible, I would have rather tried to solve that first.
    – nullpointer
    Nov 21 at 1:20














2












2








2


1





Say we have a class like this:



class Bar {
boolean b;
}

class Foo {
String zoo;
Bar bar;
}


and then we have a class that extends Foo:



class Stew extends Foo {
public Stew(Bar b, String z){
this.bar = b;
this.zoo = z;
}
}


my question is - is there any way to prevent Stew from having any non-method fields that aren't in Foo? In other words, I don't want Stew to have any fields, I just want Stew to implement a constructor and maybe a method or two.



Perhaps there is an annotation I can use, that can do this?



Something like:



@OnlyAddsMethods
class Stew extends Foo {
public Stew(Bar b, String z){
this.bar = b;
this.zoo = z;
}
}


purpose - I am going to serialize Stew to JSON, but I don't want Stew to have any new fields. I want to let any developer working on this file to know that any additional fields will be ignored (or won't be recognized) etc.










share|improve this question















Say we have a class like this:



class Bar {
boolean b;
}

class Foo {
String zoo;
Bar bar;
}


and then we have a class that extends Foo:



class Stew extends Foo {
public Stew(Bar b, String z){
this.bar = b;
this.zoo = z;
}
}


my question is - is there any way to prevent Stew from having any non-method fields that aren't in Foo? In other words, I don't want Stew to have any fields, I just want Stew to implement a constructor and maybe a method or two.



Perhaps there is an annotation I can use, that can do this?



Something like:



@OnlyAddsMethods
class Stew extends Foo {
public Stew(Bar b, String z){
this.bar = b;
this.zoo = z;
}
}


purpose - I am going to serialize Stew to JSON, but I don't want Stew to have any new fields. I want to let any developer working on this file to know that any additional fields will be ignored (or won't be recognized) etc.







java json serialization java-8






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 at 1:10

























asked Nov 21 at 1:00









Alexander Mills

17.8k30150300




17.8k30150300








  • 2




    At compile time? At runtime? Why do you consider fields a problem that needs preventing?
    – meriton
    Nov 21 at 1:03










  • The question would be why do you need Stew to extend Foo and prior to that why do you need bar and zoo in Foo? You can always choose to have a constructor which doesn't need to initialize the properties of parent class. Is that what you're looking for?
    – nullpointer
    Nov 21 at 1:03






  • 1




    If you go the annotation route, you can create an annotation processor that emits errors if you declare any fields inside a class with the corresponding annotation. This would happen during compilation.
    – Slaw
    Nov 21 at 1:06








  • 1




    @AlexanderMills I got the problem statement, just wanted to mark question-related. Also, why in such case is Stew even extending Foo from a design perspective?
    – nullpointer
    Nov 21 at 1:17








  • 1




    @AlexanderMills No, I don't. You could have generated the provided constructor in Foo itself. If that's not possible, I would have rather tried to solve that first.
    – nullpointer
    Nov 21 at 1:20














  • 2




    At compile time? At runtime? Why do you consider fields a problem that needs preventing?
    – meriton
    Nov 21 at 1:03










  • The question would be why do you need Stew to extend Foo and prior to that why do you need bar and zoo in Foo? You can always choose to have a constructor which doesn't need to initialize the properties of parent class. Is that what you're looking for?
    – nullpointer
    Nov 21 at 1:03






  • 1




    If you go the annotation route, you can create an annotation processor that emits errors if you declare any fields inside a class with the corresponding annotation. This would happen during compilation.
    – Slaw
    Nov 21 at 1:06








  • 1




    @AlexanderMills I got the problem statement, just wanted to mark question-related. Also, why in such case is Stew even extending Foo from a design perspective?
    – nullpointer
    Nov 21 at 1:17








  • 1




    @AlexanderMills No, I don't. You could have generated the provided constructor in Foo itself. If that's not possible, I would have rather tried to solve that first.
    – nullpointer
    Nov 21 at 1:20








2




2




At compile time? At runtime? Why do you consider fields a problem that needs preventing?
– meriton
Nov 21 at 1:03




At compile time? At runtime? Why do you consider fields a problem that needs preventing?
– meriton
Nov 21 at 1:03












The question would be why do you need Stew to extend Foo and prior to that why do you need bar and zoo in Foo? You can always choose to have a constructor which doesn't need to initialize the properties of parent class. Is that what you're looking for?
– nullpointer
Nov 21 at 1:03




The question would be why do you need Stew to extend Foo and prior to that why do you need bar and zoo in Foo? You can always choose to have a constructor which doesn't need to initialize the properties of parent class. Is that what you're looking for?
– nullpointer
Nov 21 at 1:03




1




1




If you go the annotation route, you can create an annotation processor that emits errors if you declare any fields inside a class with the corresponding annotation. This would happen during compilation.
– Slaw
Nov 21 at 1:06






If you go the annotation route, you can create an annotation processor that emits errors if you declare any fields inside a class with the corresponding annotation. This would happen during compilation.
– Slaw
Nov 21 at 1:06






1




1




@AlexanderMills I got the problem statement, just wanted to mark question-related. Also, why in such case is Stew even extending Foo from a design perspective?
– nullpointer
Nov 21 at 1:17






@AlexanderMills I got the problem statement, just wanted to mark question-related. Also, why in such case is Stew even extending Foo from a design perspective?
– nullpointer
Nov 21 at 1:17






1




1




@AlexanderMills No, I don't. You could have generated the provided constructor in Foo itself. If that's not possible, I would have rather tried to solve that first.
– nullpointer
Nov 21 at 1:20




@AlexanderMills No, I don't. You could have generated the provided constructor in Foo itself. If that's not possible, I would have rather tried to solve that first.
– nullpointer
Nov 21 at 1:20












3 Answers
3






active

oldest

votes


















3














The Java Language offers no built-in way to prevent a subclass from adding fields.



You might be able to write an annotation processor (which are essentially plugins for the java compiler) to enforce such an annotation, or use the reflection api to inspect subclass field declarations in the superclass constructor or a unit test. The former offers compile time support and possibly even IDE support, but is much harder to implement than the latter.



The latter could look something like this:



public class Super {
protected Super() {
for (Class<?> c = getClass(); c != Super.class; c = c.getSuperClass()) {
if (c.getDeclaredFields().length > 0) {
throw new IllegalApiUseException();
}
}
}
}


You might want to permit static fields, and add nicer error messages.






share|improve this answer































    2














    That would be an odd feature.



    You could use, say, a javac processor to check at compile time or reflection at runtime, but that would be an odd choice.



    A better approach is to change the design.



    Delegation is usually a better choice than inheritance.



    So, what can we pass in to the constructor that wont have state. An enum is the perfect match. It could have global state, but you really can't check for that unfortunately.



    interface FooStrategy {
    MyRet fn(Foo foo, MyArg myArg);
    }
    public final class Foo<S extends Enum<S> & FooStrategy> {
    private final S strategy;
    private String zoo;
    private Bar bar;
    public Foo(S strategy, Bar bar, String zoo) {
    this.strategy = strategy;
    this.bar = bar;
    this.zoo = zoo;
    }
    // For any additional methods the enum class may provide.
    public S strategy() {
    return strategy;
    }
    public MyRet fn(Foo foo, MyArg myArg) {
    return strategy.fn(this, myArg);
    }
    ...
    }


    You can use a different interface (and object) for the strategy to work on Foo, they probably shouldn't be the same.



    Also strategy should probably return a different type.






    share|improve this answer





























      1














      You can't force the client code to have classes without fields, but you can make the serialization mechanism ignore them. For example, when using Gson, this strategy



      class OnlyFooBar implements ExclusionStrategy {
      private static final Class<Bar> BAR_CLASS = Bar.class;
      private static final Set<String> BAR_FIELDS = fieldsOf(BAR_CLASS);
      private static final Class<Foo> FOO_CLASS = Foo.class;
      private static final Set<String> FOO_FIELDS = fieldsOf(FOO_CLASS);

      private static Set<String> fieldsOf(Class clazz) {
      return Arrays.stream(clazz.getDeclaredFields())
      .map(Field::getName)
      .collect(Collectors.toSet());
      }

      @Override
      public boolean shouldSkipField(FieldAttributes f) {
      String field = f.getName();
      Class<?> clazz = f.getDeclaringClass();
      return !(BAR_CLASS.equals(clazz) && BAR_FIELDS.contains(field)
      || FOO_CLASS.equals(clazz) && FOO_FIELDS.contains(field));
      }

      @Override
      public boolean shouldSkipClass(Class<?> clazz) {
      return false;
      }
      }


      when used in a Gson, will ignore all other fields except required ones:



      Gson gson = new GsonBuilder().setPrettyPrinting()
      .addSerializationExclusionStrategy(new OnlyFooBar())
      .create();





      share|improve this answer





















        Your Answer






        StackExchange.ifUsing("editor", function () {
        StackExchange.using("externalEditor", function () {
        StackExchange.using("snippets", function () {
        StackExchange.snippets.init();
        });
        });
        }, "code-snippets");

        StackExchange.ready(function() {
        var channelOptions = {
        tags: "".split(" "),
        id: "1"
        };
        initTagRenderer("".split(" "), "".split(" "), channelOptions);

        StackExchange.using("externalEditor", function() {
        // Have to fire editor after snippets, if snippets enabled
        if (StackExchange.settings.snippets.snippetsEnabled) {
        StackExchange.using("snippets", function() {
        createEditor();
        });
        }
        else {
        createEditor();
        }
        });

        function createEditor() {
        StackExchange.prepareEditor({
        heartbeatType: 'answer',
        autoActivateHeartbeat: false,
        convertImagesToLinks: true,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: 10,
        bindNavPrevention: true,
        postfix: "",
        imageUploader: {
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        },
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        });


        }
        });














        draft saved

        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53403857%2fextend-class-without-adding-any-new-fields%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        3 Answers
        3






        active

        oldest

        votes








        3 Answers
        3






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes









        3














        The Java Language offers no built-in way to prevent a subclass from adding fields.



        You might be able to write an annotation processor (which are essentially plugins for the java compiler) to enforce such an annotation, or use the reflection api to inspect subclass field declarations in the superclass constructor or a unit test. The former offers compile time support and possibly even IDE support, but is much harder to implement than the latter.



        The latter could look something like this:



        public class Super {
        protected Super() {
        for (Class<?> c = getClass(); c != Super.class; c = c.getSuperClass()) {
        if (c.getDeclaredFields().length > 0) {
        throw new IllegalApiUseException();
        }
        }
        }
        }


        You might want to permit static fields, and add nicer error messages.






        share|improve this answer




























          3














          The Java Language offers no built-in way to prevent a subclass from adding fields.



          You might be able to write an annotation processor (which are essentially plugins for the java compiler) to enforce such an annotation, or use the reflection api to inspect subclass field declarations in the superclass constructor or a unit test. The former offers compile time support and possibly even IDE support, but is much harder to implement than the latter.



          The latter could look something like this:



          public class Super {
          protected Super() {
          for (Class<?> c = getClass(); c != Super.class; c = c.getSuperClass()) {
          if (c.getDeclaredFields().length > 0) {
          throw new IllegalApiUseException();
          }
          }
          }
          }


          You might want to permit static fields, and add nicer error messages.






          share|improve this answer


























            3












            3








            3






            The Java Language offers no built-in way to prevent a subclass from adding fields.



            You might be able to write an annotation processor (which are essentially plugins for the java compiler) to enforce such an annotation, or use the reflection api to inspect subclass field declarations in the superclass constructor or a unit test. The former offers compile time support and possibly even IDE support, but is much harder to implement than the latter.



            The latter could look something like this:



            public class Super {
            protected Super() {
            for (Class<?> c = getClass(); c != Super.class; c = c.getSuperClass()) {
            if (c.getDeclaredFields().length > 0) {
            throw new IllegalApiUseException();
            }
            }
            }
            }


            You might want to permit static fields, and add nicer error messages.






            share|improve this answer














            The Java Language offers no built-in way to prevent a subclass from adding fields.



            You might be able to write an annotation processor (which are essentially plugins for the java compiler) to enforce such an annotation, or use the reflection api to inspect subclass field declarations in the superclass constructor or a unit test. The former offers compile time support and possibly even IDE support, but is much harder to implement than the latter.



            The latter could look something like this:



            public class Super {
            protected Super() {
            for (Class<?> c = getClass(); c != Super.class; c = c.getSuperClass()) {
            if (c.getDeclaredFields().length > 0) {
            throw new IllegalApiUseException();
            }
            }
            }
            }


            You might want to permit static fields, and add nicer error messages.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 21 at 1:20

























            answered Nov 21 at 1:12









            meriton

            52k1379143




            52k1379143

























                2














                That would be an odd feature.



                You could use, say, a javac processor to check at compile time or reflection at runtime, but that would be an odd choice.



                A better approach is to change the design.



                Delegation is usually a better choice than inheritance.



                So, what can we pass in to the constructor that wont have state. An enum is the perfect match. It could have global state, but you really can't check for that unfortunately.



                interface FooStrategy {
                MyRet fn(Foo foo, MyArg myArg);
                }
                public final class Foo<S extends Enum<S> & FooStrategy> {
                private final S strategy;
                private String zoo;
                private Bar bar;
                public Foo(S strategy, Bar bar, String zoo) {
                this.strategy = strategy;
                this.bar = bar;
                this.zoo = zoo;
                }
                // For any additional methods the enum class may provide.
                public S strategy() {
                return strategy;
                }
                public MyRet fn(Foo foo, MyArg myArg) {
                return strategy.fn(this, myArg);
                }
                ...
                }


                You can use a different interface (and object) for the strategy to work on Foo, they probably shouldn't be the same.



                Also strategy should probably return a different type.






                share|improve this answer


























                  2














                  That would be an odd feature.



                  You could use, say, a javac processor to check at compile time or reflection at runtime, but that would be an odd choice.



                  A better approach is to change the design.



                  Delegation is usually a better choice than inheritance.



                  So, what can we pass in to the constructor that wont have state. An enum is the perfect match. It could have global state, but you really can't check for that unfortunately.



                  interface FooStrategy {
                  MyRet fn(Foo foo, MyArg myArg);
                  }
                  public final class Foo<S extends Enum<S> & FooStrategy> {
                  private final S strategy;
                  private String zoo;
                  private Bar bar;
                  public Foo(S strategy, Bar bar, String zoo) {
                  this.strategy = strategy;
                  this.bar = bar;
                  this.zoo = zoo;
                  }
                  // For any additional methods the enum class may provide.
                  public S strategy() {
                  return strategy;
                  }
                  public MyRet fn(Foo foo, MyArg myArg) {
                  return strategy.fn(this, myArg);
                  }
                  ...
                  }


                  You can use a different interface (and object) for the strategy to work on Foo, they probably shouldn't be the same.



                  Also strategy should probably return a different type.






                  share|improve this answer
























                    2












                    2








                    2






                    That would be an odd feature.



                    You could use, say, a javac processor to check at compile time or reflection at runtime, but that would be an odd choice.



                    A better approach is to change the design.



                    Delegation is usually a better choice than inheritance.



                    So, what can we pass in to the constructor that wont have state. An enum is the perfect match. It could have global state, but you really can't check for that unfortunately.



                    interface FooStrategy {
                    MyRet fn(Foo foo, MyArg myArg);
                    }
                    public final class Foo<S extends Enum<S> & FooStrategy> {
                    private final S strategy;
                    private String zoo;
                    private Bar bar;
                    public Foo(S strategy, Bar bar, String zoo) {
                    this.strategy = strategy;
                    this.bar = bar;
                    this.zoo = zoo;
                    }
                    // For any additional methods the enum class may provide.
                    public S strategy() {
                    return strategy;
                    }
                    public MyRet fn(Foo foo, MyArg myArg) {
                    return strategy.fn(this, myArg);
                    }
                    ...
                    }


                    You can use a different interface (and object) for the strategy to work on Foo, they probably shouldn't be the same.



                    Also strategy should probably return a different type.






                    share|improve this answer












                    That would be an odd feature.



                    You could use, say, a javac processor to check at compile time or reflection at runtime, but that would be an odd choice.



                    A better approach is to change the design.



                    Delegation is usually a better choice than inheritance.



                    So, what can we pass in to the constructor that wont have state. An enum is the perfect match. It could have global state, but you really can't check for that unfortunately.



                    interface FooStrategy {
                    MyRet fn(Foo foo, MyArg myArg);
                    }
                    public final class Foo<S extends Enum<S> & FooStrategy> {
                    private final S strategy;
                    private String zoo;
                    private Bar bar;
                    public Foo(S strategy, Bar bar, String zoo) {
                    this.strategy = strategy;
                    this.bar = bar;
                    this.zoo = zoo;
                    }
                    // For any additional methods the enum class may provide.
                    public S strategy() {
                    return strategy;
                    }
                    public MyRet fn(Foo foo, MyArg myArg) {
                    return strategy.fn(this, myArg);
                    }
                    ...
                    }


                    You can use a different interface (and object) for the strategy to work on Foo, they probably shouldn't be the same.



                    Also strategy should probably return a different type.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Nov 21 at 1:36









                    Tom Hawtin - tackline

                    125k28179268




                    125k28179268























                        1














                        You can't force the client code to have classes without fields, but you can make the serialization mechanism ignore them. For example, when using Gson, this strategy



                        class OnlyFooBar implements ExclusionStrategy {
                        private static final Class<Bar> BAR_CLASS = Bar.class;
                        private static final Set<String> BAR_FIELDS = fieldsOf(BAR_CLASS);
                        private static final Class<Foo> FOO_CLASS = Foo.class;
                        private static final Set<String> FOO_FIELDS = fieldsOf(FOO_CLASS);

                        private static Set<String> fieldsOf(Class clazz) {
                        return Arrays.stream(clazz.getDeclaredFields())
                        .map(Field::getName)
                        .collect(Collectors.toSet());
                        }

                        @Override
                        public boolean shouldSkipField(FieldAttributes f) {
                        String field = f.getName();
                        Class<?> clazz = f.getDeclaringClass();
                        return !(BAR_CLASS.equals(clazz) && BAR_FIELDS.contains(field)
                        || FOO_CLASS.equals(clazz) && FOO_FIELDS.contains(field));
                        }

                        @Override
                        public boolean shouldSkipClass(Class<?> clazz) {
                        return false;
                        }
                        }


                        when used in a Gson, will ignore all other fields except required ones:



                        Gson gson = new GsonBuilder().setPrettyPrinting()
                        .addSerializationExclusionStrategy(new OnlyFooBar())
                        .create();





                        share|improve this answer


























                          1














                          You can't force the client code to have classes without fields, but you can make the serialization mechanism ignore them. For example, when using Gson, this strategy



                          class OnlyFooBar implements ExclusionStrategy {
                          private static final Class<Bar> BAR_CLASS = Bar.class;
                          private static final Set<String> BAR_FIELDS = fieldsOf(BAR_CLASS);
                          private static final Class<Foo> FOO_CLASS = Foo.class;
                          private static final Set<String> FOO_FIELDS = fieldsOf(FOO_CLASS);

                          private static Set<String> fieldsOf(Class clazz) {
                          return Arrays.stream(clazz.getDeclaredFields())
                          .map(Field::getName)
                          .collect(Collectors.toSet());
                          }

                          @Override
                          public boolean shouldSkipField(FieldAttributes f) {
                          String field = f.getName();
                          Class<?> clazz = f.getDeclaringClass();
                          return !(BAR_CLASS.equals(clazz) && BAR_FIELDS.contains(field)
                          || FOO_CLASS.equals(clazz) && FOO_FIELDS.contains(field));
                          }

                          @Override
                          public boolean shouldSkipClass(Class<?> clazz) {
                          return false;
                          }
                          }


                          when used in a Gson, will ignore all other fields except required ones:



                          Gson gson = new GsonBuilder().setPrettyPrinting()
                          .addSerializationExclusionStrategy(new OnlyFooBar())
                          .create();





                          share|improve this answer
























                            1












                            1








                            1






                            You can't force the client code to have classes without fields, but you can make the serialization mechanism ignore them. For example, when using Gson, this strategy



                            class OnlyFooBar implements ExclusionStrategy {
                            private static final Class<Bar> BAR_CLASS = Bar.class;
                            private static final Set<String> BAR_FIELDS = fieldsOf(BAR_CLASS);
                            private static final Class<Foo> FOO_CLASS = Foo.class;
                            private static final Set<String> FOO_FIELDS = fieldsOf(FOO_CLASS);

                            private static Set<String> fieldsOf(Class clazz) {
                            return Arrays.stream(clazz.getDeclaredFields())
                            .map(Field::getName)
                            .collect(Collectors.toSet());
                            }

                            @Override
                            public boolean shouldSkipField(FieldAttributes f) {
                            String field = f.getName();
                            Class<?> clazz = f.getDeclaringClass();
                            return !(BAR_CLASS.equals(clazz) && BAR_FIELDS.contains(field)
                            || FOO_CLASS.equals(clazz) && FOO_FIELDS.contains(field));
                            }

                            @Override
                            public boolean shouldSkipClass(Class<?> clazz) {
                            return false;
                            }
                            }


                            when used in a Gson, will ignore all other fields except required ones:



                            Gson gson = new GsonBuilder().setPrettyPrinting()
                            .addSerializationExclusionStrategy(new OnlyFooBar())
                            .create();





                            share|improve this answer












                            You can't force the client code to have classes without fields, but you can make the serialization mechanism ignore them. For example, when using Gson, this strategy



                            class OnlyFooBar implements ExclusionStrategy {
                            private static final Class<Bar> BAR_CLASS = Bar.class;
                            private static final Set<String> BAR_FIELDS = fieldsOf(BAR_CLASS);
                            private static final Class<Foo> FOO_CLASS = Foo.class;
                            private static final Set<String> FOO_FIELDS = fieldsOf(FOO_CLASS);

                            private static Set<String> fieldsOf(Class clazz) {
                            return Arrays.stream(clazz.getDeclaredFields())
                            .map(Field::getName)
                            .collect(Collectors.toSet());
                            }

                            @Override
                            public boolean shouldSkipField(FieldAttributes f) {
                            String field = f.getName();
                            Class<?> clazz = f.getDeclaringClass();
                            return !(BAR_CLASS.equals(clazz) && BAR_FIELDS.contains(field)
                            || FOO_CLASS.equals(clazz) && FOO_FIELDS.contains(field));
                            }

                            @Override
                            public boolean shouldSkipClass(Class<?> clazz) {
                            return false;
                            }
                            }


                            when used in a Gson, will ignore all other fields except required ones:



                            Gson gson = new GsonBuilder().setPrettyPrinting()
                            .addSerializationExclusionStrategy(new OnlyFooBar())
                            .create();






                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Nov 22 at 20:30









                            jihor

                            1,427618




                            1,427618






























                                draft saved

                                draft discarded




















































                                Thanks for contributing an answer to Stack Overflow!


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.





                                Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                                Please pay close attention to the following guidance:


                                • Please be sure to answer the question. Provide details and share your research!

                                But avoid



                                • Asking for help, clarification, or responding to other answers.

                                • Making statements based on opinion; back them up with references or personal experience.


                                To learn more, see our tips on writing great answers.




                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53403857%2fextend-class-without-adding-any-new-fields%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                Popular posts from this blog

                                404 Error Contact Form 7 ajax form submitting

                                How to know if a Active Directory user can login interactively

                                Refactoring coordinates for Minecraft Pi buildings written in Python