Problems about java syntax [duplicate] - jvm

This question already has answers here:
Can a java file have more than one class?
(18 answers)
Closed 8 years ago.
Here's the code :
public class EmployeeTest
{
public static void main(String args[]){
//System.out.println("hello world");
Employee aEmployee = new Employee("David",1000);
System.out.println(aEmployee.getName() + aEmployee.getSalary());
}
}
class Employee // **why can't I put a "public" here**
{
// Constructor
public Employee(String name, double salary)
{
this.name = name;
this.salary = salary;
}
// Methods
public String getName()
{
return this.name;
}
public double getSalary()
{
return this.salary;
}
// instance field
private String name;
private double salary;
}
My question is : in the second class definition's first line, why can't I put a "public" to define it ?
What's the exactly meaning of "public" when using it defines a class ?

This is language feature. There must be only one top-level public class per .java file and public class name must match the source java file name.
Basically, non-public types are not accessible outside the package so if you wish to allow type to be used anywhere then make it public.
Never create a type in default package. (Always use package)
Employee.java
package com.abc.model;
public class Employee{..}
EmployeeTest.java
package com.abc.test;
public class EmployeeTest{ ... }

Because a Java source file can have at most one top-level public class or interface, and the name of the source file must be the same as the name of that class or interface.
That's a rule that the Java compiler of Oracle's JDK imposes.

In Java, there can only be a single public top level class per source file and it needs to be named the same as the file.
This is useful for the compiler when it needs to locate a class definition from outside the package, since it knows the type name, it knows which class file to find the class in. For example. since a jar file is in essence a zip file with class files, this prevents the compiler from having to unzip the entire jar to find a class definition.
The Java language specification §7.6 specifies this as an optional restriction;
If and only if packages are stored in a file system (§7.2), the host
system may choose to enforce the restriction that it is a compile-time
error if a type is not found in a file under a name composed of the
type name plus an extension (such as .java or .jav) if either of the
following is true:
The type is referred to by code in other compilation units of the
package in which the type is declared.
The type is declared public (and therefore is potentially accessible
from code in other packages).

you can define a public class inside a public class which is legal.
public class EmployeeTest
{
public class Employee {
}
}

Related

Finding the annotated method call as a parameter to Logger methods

Suppose I have below Person class with one getAccountNumber() method having #ShouldNotBeLogged custom annotation.
public class Person {
private String name;
private String accountNumber;
#ShouldNotBeLogged
public String getAccountNumber() {
return accountNumber;
}
}
Considering the above Person class I want to find the all occurrences where getAccountNumber() method is logged using the Logger class - error|warn|debug|info methods like in the below HelloWorld class logMessage method. Please note that there are many methods having ShouldNotBeLogged annotation in the actual code, so we cannot create search with name of the method in it.
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class HelloWorld {
private static final Logger logger = LogManager.getLogger(HelloWorld.class);
public void logMessage(Person person) {
logger.debug("logging Acc No. - {}", person.getAccountNumber()); // Occurence Type 1
LogManager.getLogger(HelloWorld.class).info("Account Number - {}", person.getAccountNumber()); // Occurence Type 2
}
}
I have tried using the Method call existing template and given the Text filter for $MethodCall$ with - error|warn|debug|info and it finds the Logger method with the error,warn,debug or, info names. Not able to create the filter for $Instance$ & $Parameter$ where Instance will be of Logger type (can be instantiated as a constant of a class or, directly with the Logger class method) and Parameter will be the call to #ShouldNotBeLogged annotated method.
$Instance$.$MethodCall$($Parameter$)
I'm using the IntelliJ IDEA 2022.2 (Ultimate Edition)
This is a difficult case. Hopefully this will help you.
First, create a search that will find #ShouldNotBeLogged annotated methods:
#ShouldNotBeLogged
$ReturnType$ $Method$($ParameterType$ $Parameter$);
With a count modifier [0,∞] on $Parameter$ (this template is based on the existing template "Deprecated methods"). Save this template under a name, for example "Methods that should not be logged".
$logger$.$call$($arg1$, $method$())
Modifiers:
$logger$: type=Logger
$method$: reference=Methods that should not be logged
This will find all logger calls with a call to a #ShouldNotBeLogged annotated method as the second argument.
Unfortunately, if you want to find logger calls with calls to a #ShouldNotBeLogged annotated method on a different position, you will have to construct a separate query template. For example:
$logger$.$call$($arg1$, $arg2$, $method$())

redefine static methods with ByteBuddy

Can homebody help me please to give me a hint how to redefine static methods using byte-buddy 1.6.9 ?
I have tried this :
public class Source {
public static String hello(String name) {return null;}
}
public class Target {
public static String hello(String name) {
return "Hello" + name+ "!";
}
}
String helloWorld = new ByteBuddy()
.redefine(Source.class)
.method(named("hello"))
.intercept(MethodDelegation.to(Target.class))
.make()
.load(getClass().getClassLoader())
.getLoaded()
.newInstance()
.hello("World");
I got following Exception :
Exception in thread "main" java.lang.IllegalStateException: Cannot inject already loaded type: class delegation.Source
Thanks
Classes can only be loaded once by each class loader. In order to replace a method, you would need to use a Java agent to hook into the JVM's HotSwap feature.
Byte Buddy provides a class loading strategy that uses such an agent, use:
.load(Source.class.getClassLoader(),
ClassReloadingStrategy.fromInstalledAgent());
This does however require you to install a Java agent. On a JDK, you can do so programmatically, by ByteBuddyAgent.install() (included in the byte-buddy-agent artifact). On a JVM, you have to specify the agent on the command line.

JavaFX Wrap an Existing Object with Simple Properties

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.

unable to chain up to base constructor requiring arguments

public class Font : SDLTTF.Font {
public Font (string _filename, int _size) {
}
public void draw () {
}
}
That's my code. When I try to build it, I get:
Font.vala:4.5-4.15: error: unable to chain up to base constructor requiring arguments
public Font (string _filename, int _size) {
^^^^^^^^^^^
Compilation failed: 1 error(s), 0 warning(s)
I thought I needed to override the constructor, so I tried to public override it, but now I get:
Font.vala:4.5-4.24: error: abstract, virtual, and override modifiers are not applicable to creation methods
public override Font (string _filename, int _size) {
^^^^^^^^^^^^^^^^^^^^
Compilation failed: 1 error(s), 0 warning(s)
Any ideas on how to fix this? I'm trying to inherit the SDLTTF.Font class.
Have you tried putting
base(_filename, _size);
in your constructor?
EDIT:
This worked for me. Note however that SDLTTF.Font is defined in the vapi as a compact class, meaning that when you derive it, you're only allowed to define new functions for your subclass, but no instance data (member variables, etc.). If you require this, I'd recommend you go with apmasell's suggestion and create a wrapper class deriving from (G)Object.
SDLTTF is not managed by GObject, so Vala cannot create a derived class. Vala can only create derived classes if they make use of GObject, as is typical in GLib, GTK+, Pango, ATK, and many GNOME libraries.
Depending on what you want to do, you could create a new class that contains an instance of SDLTFF.Font and proxy the appropriate requests.

Set non-injected parameters when importing objects using MEF

I have the following scenario in my Silverlight 4 application:
public class TheViewModel
{
[Import()]
public TheChild Child { get; set; }
}
[Export()]
public class TheChild
{
[ImportingConstructor()]
public TheChild(String myName, IAmTheService service) { ... }
}
[Export(typeof(IAmTheService))]
public class TheService : IAmTheService
{
public void DoSomething(String theName);
}
As you can see, TheChild's constructor requires one imported parameter and one static value that is context-sensitive (has to be provided by the parent). The string value cannot come from AppSettings, configuration, etc. and can only be provided by the current instance of the parent class (TheViewModel in this case).
As a rule-of-thumb, I've always approached dependency-injection as follows:
Required dependencies are satisfied through constructor injection
Optional dependencies are satisfied through property injection
The "myName" parameter is required so I would prefer to set it through the constructor but given the way MEF works, I realize this may have to change.
Can you tell me how you've handled this scenario and your thoughts behind the solution?
You can specify a specific import contract in conjunction with [ImportingConstructor]. For example:
[Export()]
public class TheChild
{
[ImportingConstructor()]
public TheChild([Import("MyName")] String myName, IAmTheService service) { ... }
Given that, an export of a string decorated with [Export("MyName")] will be required and used to fulfill the dependency. Any of the [Import] specifications should work in this case (ie: importing a subclass by type, importing by name, etc).