I have a class that looks like this:
public class MyClass {
private class MyInnerClass {
public void someFunc() { }
}
public void usefulMethod() {
... some stuff...
nativeUsefulMethod();
}
private native void nativeUsefulMethod();
}
I need to keep the method names of all native functions, as well as the classes containing them, in order for the native code to work properly. Seems like no problem:
-keepnames class * {
native <methods>;
}
When I look at the resulting jar, I see that MyClass and nativeUsefulMethod() remain, while usefulMethod() has been obfuscated. Good. However, the inner class is still named "MyClass$MyInnerClass". It contains no native methods, so I would expect it to be called "MyClass$a" or just "a".
I tested changing "-keepnames" to "-keepclassmembernames", and the class names of both get obfuscated. It's definitely this directive that's keeping the inner class name. Is there a way to obfuscate the outer, but not the inner class name?
The proper configuration for native methods is:
-keepclasseswithmembernames class * {
native <methods>;
}
See the ProGuard manual > Examples > Processing native methods
Related
I am writing a new app and I have chosen to use Java for flexibility. It is a GUI app so I will use JavaFX. This is my first time using Java but I have experience with C#.
I am getting familiar with JavaFX Properties, they look like a great way of bi-directional binding between front-end and back-end.
My code uses classes from an open-source API, and I would like to convert the members of these classes to JavaFX Properties (String => StringProperty, etc). I believe this would be transparent to any objects that refer to these members.
Is it ok to do this?
Is it the suggested way of dealing with existing classes?
What do I do about Enum types? E.g. an enum member has it's value changed, how should I connect the enum member to the front-end?
Thank you :)
In general, as long as you don't change the public API of the class - in other words you don't remove any public methods, modify their parameter types or return types, or change their functionality - you should not break any code that uses them.
So, e.g. a change from
public class Foo {
private String bar ;
public String getBar() {
return bar ;
}
public void setBar(String bar) {
this.bar = bar ;
}
}
to
public class Foo {
private final StringProperty bar = new SimpleStringProperty();
public StringProperty barProperty() {
return bar ;
}
public String getBar() {
return barProperty().get();
}
public void setBar(String bar) {
barProperty().set(bar);
}
}
should not break any clients of the class Foo. The only possible problem is that classes that have subclassed Foo and overridden getBar() and/or setBar(...) might get unexpected behavior if their superclass is replaced with the new implementation (specifically, if getBar() and setBar(...) are not final, you have no way to enforce that getBar()==barProperty().get(), which is desirable).
For enums (and other objects) you can use an ObjectProperty<>:
Given
public enum Option { FIRST_CHOICE, SECOND_CHOICE, THIRD_CHOICE }
Then you can do
public class Foo {
private final ObjectProperty<Option> option = new SimpleObjectProperty<>();
public ObjectProperty<Option> optionProperty() {
return option ;
}
public Option getOption() {
return optionProperty().get();
}
public void setOption(Option choice) {
optionProperty().set(choice);
}
}
One caveat to all this is that you do introduce a dependency on the JavaFX API that wasn't previously present in these classes. JavaFX ships with the Oracle JDK, but it is not a full part of the JSE (e.g. it is not included in OpenJDK by default, and not included in some other JSE implementations). So in practice, you're highly unlikely to be able to persuade the developers of the open source library to accept your changes to the classes in the library. Since it's open source, you can of course maintain your own fork of the library with JavaFX properties, but then it will get tricky if you want to incorporate new versions of that library (you will need to merge two different sets of changes, essentially).
Another option is to use bound properties in the classes, and wrap them using a Java Bean Property Adapter. This is described in this question.
I have a class C which is derived from a generic class D. I referenced the class C in a XAML file. When I build the app, I get the following error:
The tag 'C' does not exist in XML namespace 'clr-namespace:A.B'
I don't understand is this due to C is derived from a generic class. If I remove the base class, it does not give me any error.
How can I get rid of the error? The IInterfaceForE is injected via Unity, so the app works fine. But I can't get rid of the build error.
Code snippet:
namespace A.B
{
public class C : D<InterfaceForE>
{
public C()
{
}
}
}
// Reference in XAML
xmlns:myns="clr-namespace:A.B"
<myns:C x:Key="KeyForC"/>
// Code snippet after commenting out the base class.
// When I build with this code, there is no build error, but the app wont run.
namespace A.B
{
public class C //: D<InterfaceForE>
{
public C()
{
}
}
}
I had to remove the generic being used to make this work.
I'm trying to make a Script# import library to wrap (parts of) the dojo toolkit--especially the dijit widgets. Unfortunately, dojo uses multiple inheritance, and C# doesn't support that (except for interfaces, which Script# doesn't handle properly--see below).
I'm trying to accomplish something like this:
[Imported]
public class A
{
public void Foo() {}
}
[Imported]
public class B
{
public void Bar() {}
}
[Imported]
public class C : A, B
{
public void Sproing() {}
}
but obviously that's not valid C#, and therefore isn't valid Script#.
Is there a way in Script# to accommodate multiple inheritance of [Imported] classes? I tried using interfaces, since C# supports multiple inheritance of them and I'm not providing implementations anyway:
[Imported]
public interface A
{
void Foo();
}
[Imported]
public interface B
{
void Bar();
}
[Imported]
public interface C : A, B
{
void Sproing();
}
however, when I try to use the library from another Script# project, code such as C c = null; c.Foo(); I just get a "Check that your C# source compiles and that you are not using an unsupported feature. Common things to check for include use of fully-qualified names (use a using statement to import namespaces instead) or accessing private members of a type from a static member of the same type." error on the c.Foo() call.
Any other ideas? The [Mixin] attribute doesn't appear to do what I need either.
The only other option I see at the moment (aside from fixing the interfaces problem in Script#, which I'm not prepared to do) is to ditch inheritance altogether and put all the
"inherited" members in each leaf class. That would look something like this:
[Imported]
public class A
{
public void Foo() {}
}
[Imported]
public class B
{
public void Bar() {}
}
[Imported]
public class C
{
public void Foo() {}
public void Bar() {}
public void Sproing() {}
}
Obviously that would get ugly fast, but I could automate it. Since JavaScript's type system is pretty fast-and-loose anyway, this might even work OK there. And in Script# land, consumers of the import library would simply need to do more explicit casts than they should need to do. Are there other disadvantages that I'm overlooking?
Interface inheritance isn't currently supported. It will be fixed in a future rev.
You could define:
interface A {
}
interface B {
}
class C : A, B {
}
It does mean you'll end up having to define all members, even if stubs in C.
I haven't looked at Dojo in any depth, but potentially a better strategy will be to have a base class with methods shared across many of the widgets, and then derived widget types for each individual widget type. That would be something similar to the jQueryUI stuff that is in the script# repository.
Referring to the below link:
http://www.javaworld.com/javaworld/jw-11-1998/jw-11-techniques.html?page=2
The composition approach to code reuse provides stronger encapsulation
than inheritance, because a change to a back-end class needn't break
any code that relies only on the front-end class. For example,
changing the return type of Fruit's peel() method from the previous
example doesn't force a change in Apple's interface and therefore
needn't break Example2's code.
Surely if you change the return type of peel() (see code below) this means getPeelCount() wouldn't be able to return an int any more? Wouldn't you have to change the interface, or get a compiler error otherwise?
class Fruit {
// Return int number of pieces of peel that
// resulted from the peeling activity.
public int peel() {
System.out.println("Peeling is appealing.");
return 1;
}
}
class Apple {
private Fruit fruit = new Fruit();
public int peel() {
return fruit.peel();
}
}
class Example2 {
public static void main(String[] args) {
Apple apple = new Apple();
int pieces = apple.peel();
}
}
With a composition, changing the class Fruit doesn't necessary require you to change Apple, for example, let's change peel to return a double instead :
class Fruit {
// Return String number of pieces of peel that
// resulted from the peeling activity.
public double peel() {
System.out.println("Peeling is appealing.");
return 1.0;
}
}
Now, the class Apple will warn about a lost of precision, but your Example2 class will be just fine, because a composition is more "loose" and a change in a composed element does not break the composing class API. In our case example, just change Apple like so :
class Apple {
private Fruit fruit = new Fruit();
public int peel() {
return (int) fruit.peel();
}
}
Whereas if Apple inherited from Fruit (class Apple extends Fruit), you would not only get an error about an incompatible return type method, but you'd also get a compilation error in Example2.
** Edit **
Lets start this over and give a "real world" example of composition vs inheritance. Note that a composition is not limited to this example and there are more use case where you can use the pattern.
Example 1 : inheritance
An application draw shapes into a canvas. The application does not need to know which shapes it has to draw and the implementation lies in the concrete class inheriting the abstract class or interface. However, the application knows what and how many different concrete shapes it can create, thus adding or removing concrete shapes requires some refactoring in the application.
interface Shape {
public void draw(Graphics g);
}
class Box implement Shape {
...
public void draw(Graphics g) { ... }
}
class Ellipse implements Shape {
...
public void draw(Graphics g) { ... }
}
class ShapeCanvas extends JPanel {
private List<Shape> shapes;
...
protected void paintComponent(Graphics g) {
for (Shape s : shapes) { s.draw(g); }
}
}
Example 2 : Composition
An application is using a native library to process some data. The actual library implementation may or may not be known, and may or may not change in the future. A public interface is thus created and the actual implementation is determined at run-time. For example :
interface DataProcessorAdapter {
...
public Result process(Data data);
}
class DataProcessor {
private DataProcessorAdapter adapter;
public DataProcessor() {
try {
adapter = DataProcessorManager.createAdapter();
} catch (Exception e) {
throw new RuntimeException("Could not load processor adapter");
}
}
public Object process(Object data) {
return adapter.process(data);
}
}
static class DataProcessorManager {
static public DataProcessorAdapter createAdapter() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
String adapterClassName = /* load class name from resource bundle */;
Class<?> adapterClass = Class.forName(adapterClassName);
DataProcessorAdapter adapter = (DataProcessorAdapter) adapterClass.newInstance();
//...
return adapter;
}
}
So, as you can see, the composition may offer some advantage over inheritance in the sense that it allows more flexibility in the code. It allows the application to have a solid API while the underlaying implementation may still change during it's life cycle. Composition can significantly reduce the cost of maintenance if properly used.
For example, when implementing test cases with JUnit for Exemple 2, you may want to use a dummy processor and would setup the DataProcessorManager to return such adapter, while using a "real" adapter (perhaps OS dependent) in production without changing the application source code. Using inheritance, you would most likely hack something up, or perhaps write a lot more initialization test code.
As you can see, compisition and inheritance differ in many aspects and are not preferred over another; each depend on the problem at hand. You could even mix inheritance and composition, for example :
static interface IShape {
public void draw(Graphics g);
}
static class Shape implements IShape {
private IShape shape;
public Shape(Class<? extends IShape> shape) throws InstantiationException, IllegalAccessException {
this.shape = (IShape) shape.newInstance();
}
public void draw(Graphics g) {
System.out.print("Drawing shape : ");
shape.draw(g);
}
}
static class Box implements IShape {
#Override
public void draw(Graphics g) {
System.out.println("Box");
}
}
static class Ellipse implements IShape {
#Override
public void draw(Graphics g) {
System.out.println("Ellipse");
}
}
static public void main(String...args) throws InstantiationException, IllegalAccessException {
IShape box = new Shape(Box.class);
IShape ellipse = new Shape(Ellipse.class);
box.draw(null);
ellipse.draw(null);
}
Granted, this last example is not clean (meaning, avoid it), but it shows how composition can be used.
Bottom line is that both examples, DataProcessor and Shape are "solid" classes, and their API should not change. However, the adapter classes may change and if they do, these changes should only affect their composing container, thus limit the maintenance to only these classes and not the entire application, as opposed to Example 1 where any change require more changes throughout the application. It all depends how flexible your application needs to be.
If you would change Fruit.peel()'s return type, you would have to modify Apple.peel() as well. But you don't have to change Apple's interface.
Remember: The interface are only the method names and their signatures, NOT the implementation.
Say you'd change Fruit.peel() to return a boolean instead of a int. Then, you could still let Apple.peel() return an int. So: The interface of Apple stays the same but Fruit's changed.
If you would have use inheritance, that would not be possible: Since Fruit.peel() now returns a boolean, Apple.peel() has to return an boolean, too. So: All code that uses Apple.peel() has to be changed, too. In the composition example, ONLY Apple.peel()'s code has to be changed.
The key word in the sentence is "interface".
You'll almost always need to change the Apple class in some way to accomodate the new return type of Fruit.peel, but you don't need to change its public interface if you use composition rather than inheritance.
If Apple is a Fruit (ie, inheritance) then any change to the public interface of Fruit necessitates a change to the public interface of Apple too. If Apple has a Fruit (ie, composition) then you get to decide how to accomodate any changes to the Fruit class; you're not forced to change your public interface if you don't want to.
Return type of Fruit.peel() is being changed from int to Peel. This doesn't meant that the return type of Apple.peel() is being forced to change to Peel as well. In case of inheritance, it is forced and any client using Apple has to be changed. In case of composition, Apple.peel() still returns an integer, by calling the Peel.getPeelCount() getter and hence the client need not be changed and hence Apple's interface is not changed ( or being forced to be changed)
Well, in the composition case, Apple.peel()'s implementation needs to be updated, but its method signature can stay the same. And that means the client code (which uses Apple) does not have to be modified, retested, and redeployed.
This is in contrast to inheritance, where a change in Fruit.peel()'s method signature would require changes all way into the client code.
Please see the code below :
package bk;
public class A {
protected void methodA() {
System.out.println("Calling the method A !");
}
}
// And I have an another package :
package com;
import bk.A;
public class B extends A {
public void methodB() {
System.out.println("Goi phuong thuc B !");
}
public static void main(String[] args) {
A a = new B();
a.methodA();
}
}
How can I allow a to call methodA()?
Cause methodA() is protected and it can be called within derived classes only. Change it to public if you want to call it like this
Protected methods can only be called from within the class itself, or from derived classes.
The a variable is declared as a variable of type A. Class A itself has no publicly available methodA, so you cannot call it.
Yes, you assign a new B instance to the a variable and the a.methodA() statement is inside the derived B class, but the compiler only sees that a is of type A. It could be any other subclass of A as well, in which case you still wouldn't have access to methodA.
You'll have to tell the compiler that the a variable is actually of type B. Then you will be able to call methodA, because you're calling it from within class B.
B a = new B();
You are trying to access methodA() like it is public. Declaring simply methodA() in the B class is fine, but you cannot do a.methodA().
Conversely if it wasn't a method and simply protected int a;
you could do
a = 1; in class B
but
A a = new A();
a.a = 1;
is not legal
A protected method is visible to inheriting classes, even not part of the same package. A package scope (default) method is not. That is the only difference between protected and package scope.
The theory is that someone extending your class with protected access knows more about what they are doing than someone who is merely using it with public access. They also need more access to your class’s inner workings. Other than that, protected behaves like default package access.