SCJP6 var arg issue from Kathie siera - scjp

please help me to sort out the issues.because my answer getting different from Kathie siera book answer.for the below code i get compile error because of redeclaration to sifter(BB .
But in the book answer is "-434"
class AA{}
class BB extends AA{
}
public class ComingThru {
static String s="-";
public static void main(String args[])
{
AA aa []=new AA[2];
BB bb []=new BB[2];
sifter(aa);
System.out.println(s);
sifter(bb);
sifter(7);
System.out.println(s);
}
static void sifter(AA... a2)
{
s+="1";
}
static void sifter(BB... a2)
{
s+="2";
}
static void sifter(BB[] a3)
{
s+="2";
}
static void sifter(Object o){
s+="4";
}
}

I've checked the book, the arguments for the first two functions is not AA or BB, is an array of AA or BB:
It should be like this:
static void sifter(AA[] ... a2) {s += "1"}
static void sifter(BB[] ... b1) {s += "2"}
Attention that AA[] means that it accepts an array of array(AA[]) but not an array of AA.
So the answer in the book is correct.
PS:
In your code, it's normal that there is a compile error. Since you define both sifter(BB ... b1) and sifter(BB[] b2), the compiler cannot tell which one to choose if you pass an array of BB as argument.

Related

Doing Cyclic Types in ByteBuddy

I am trying to dynamically create cyclic classes like this with byte-buddy:
class A{
B b;
}
class B{
A a;
}
I have looked at this example and I have written this code.
public static void main(String[] args) throws Exception {
final ByteBuddy bb = new ByteBuddy();
TypeDescription.Generic g1 = TypeDescription.Generic.Builder.rawType(Object.class).build();
final InstrumentedType typeDescrB = InstrumentedType.Default.of("B", g1, Modifier.PUBLIC);
final DynamicType.Unloaded<Object> madeA = bb
.subclass(Object.class)
.name("A")
.defineField("theB", typeDescrB, Modifier.PUBLIC).make();
final DynamicType.Unloaded<Object> madeB = bb.subclass(Object.class)
.name("B")
.defineField("theA", madeA.getTypeDescription()).make();
Class a = madeA.include(madeB)
.load(Test.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
for (Field f : a.getFields()) {
System.out.println(f + "|" + f.getType().getName());
}
System.out.println("====");
for (Field f : a.getField("theB").getType().getFields()) {
System.out.println(f + "|" + f.getType().getName());
}
}
After running the code I get this results
public B A.theB|B
====
Process finished with exit code 0
which means the Class B does not contain the field a. Does anybody know what is the problem?
I'm guessing that what you're seeing is just a mistake in your code.
With this code:
final DynamicType.Unloaded<Object> madeB = bb.subclass(Object.class)
.name("B")
.defineField("theA", madeA.getTypeDescription()).make();
…you have made the field non-public (note that you specified PUBLIC for the other field, but not here). Then with this code:
for (Field f : a.getField("theB").getType().getFields()) {
System.out.println(f + "|" + f.getType().getName());
}
…you have asked for only public fields. Perhaps you meant getDeclaredFields()?

How to use ByteBuddy in a java project

I made a simple project of java to test ByteBuddy . I typed exactly the same code in a tutorial made by Rafael Winterhalter but it showing some errors
1) ByteBuddyAgent cannot be resolved.
2) type cannot be resolved to a variable.
3) builder cannot be resolved.
4) method cannot be resolved to a variable.
I added the byte-buddy-1.7.1.jar as a referenced library.
public class LogAspect {
public static void main(String[] args){
premain("", ByteBuddyAgent.installOnOpenJDK());
Calculator calculator = new Calculator();
int sum = calculator.sum(10, 15, 20);
System.out.println("Sum is "+ sum);
}
public static void premain(String arg, Instrumentation inst){
new AgentBuilder.Default()
.rebase(type -> type.getSimpleName().equals("Calculator"))
.transform((builder, typeDescription) -> builder
.method(method -> method.getDeclaredAnnotations().isAnnotationPresent(Log.class))
.intercept(MethodDelegation.to(LogAspect.class).andThen(SuperMethodCall.INSTANCE)))
.installOn(inst);
}
public static void intercept(#Origin Method method){
System.out.println(method.getName()+" is called.");
}
}
#interface Log{
}
class Calculator {
#Log
public int sum(int... values) {
return Arrays.stream(values).sum();
}
}
It looks like you are using a very outdated tutorial of the 0.* ara. Use an IDE to check your compile-time errors and check the webpage for more recent tutorials.

linked list in java insert at end

Guys I do have problem while inserting a new node at the end of a list. insert at begening works fine but in insert at end it shows null pointer exception.
Please look in method inserAtEnd and suggest me how to deal with it:
package linkedlist;
class Node{
Node next;
Object data;
Node(Object x)
{
data=x;
}
}
class LL
{
Node first;
LL(Node f)
{
first =f;
}
void insertAtBeg(Object x)
{
Node n= new Node(x);
n.next=first;
first=n;
}
void insertAtEnd(Object x)
{
Node n= new Node(x);
Node k;
k=first;
while(k!=null)
{
k=k.next;
}
k.next=n;
}
void print()
{
Node p=first;
while(p!=null)
{
System.out.print(p.data+"-->");
p=p.next;
}
}
}
public class LinkedList {
public static void main(String[] args) {
LL l = new LL(null);
l.insertAtBeg("Raj");
l.insertAtBeg("Am ");
l.insertAtBeg("I ");
l.insertAtBeg("100 ");
l.insertAtEnd("Hello");
l.print();
System.out.println("returned in main");
}
}
The problem is your loop is going till k is null, you want to go till k.next is equal to null. You could also solve it by having a variable for the last node(This is what is almost always done). The code I've provided fixes the problem without adding any new variables however:
void insertAtEnd(Object x) {
Node n= new Node(x);
Node k;
k=first;
while(k.next != null) {
k=k.next;
}
k.next=n;
}

How to define point cuts for a sequence of method(s)?

For example if I have 3 classes,
class A {
public void doA() {
/* do something */
}
}
class B {
public void doB() {
A a = new A();
a.doA();
}
}
class MyClass {
public static void main(String args[]) {
B b = new B();
b.doB();
}
}
Now I want to define a point cut for flow doB() -> doA(), like if doB() calls doA() grab parameters from class A and class B and do something in aspect method. Could someone help me out.
Let me slightly extend your sample code in order to make you understand what my solution does and what it cannot do:
class A {
public void doA() {}
}
class B {
public void doB() {
new A().doA();
new C().doC();
}
}
class C {
public void doC() {
new A().doA();
}
}
class MyClass {
public static void main(String args[]) {
new A().doA(); // should not be captured
new B().doB(); // should be captured
}
}
As you can see, there is a new class C now and we have three control flows now:
MyClass.main -> A.doA
MyClass.main -> B.doB -> A.doA
MyClass.main -> B.doB -> C.doC -> A.doA
You want to exclude #1 and capture #2, but what about #3? In this case a.doA is called indirectly from B.doB via C.doC. My solution also captures this indirect case. If this is fine for you or it does not happen in your code base, you can use my solution. Otherwise things would get a little more complicated and you would need to inspect the call stack. Tell me if you need to exclude #2, and I will extend my answer, but the solution will not look as simple as this one, I can promise.
Now here is the aspect:
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class ControlFlowInterceptor {
#Before("execution(void A.doA()) && target(a) && cflow(execution(void B.doB()) && target(b))")
public void advice(JoinPoint thisJoinPoint, A a, B b) {
System.out.println(thisJoinPoint);
System.out.println(" " + a);
System.out.println(" " + b);
}
}
The console output looks like this:
execution(void A.doA())
A#7b19f779
B#65c66812
execution(void A.doA())
A#4df2868
B#65c66812
Please note that we have the same B object ID in both outputs, but because C.doC creates an new A object, we have two different A object IDs.

Wrapper over template classes c++/cli

I am trying to create a c++ cli/clr wrapper over a project based on .hpp files (that does not generate .dll or .lib). My problem is as follows:
Let's say I have:
class A
{
A();
void DoAStuff();
}
class B
{
B();
void DoBStuff();
}
class C
{
C();
void DoCStuff();
}
template <typename AorB>
class AB
{
AB();
AorB GetAB();
}
template <typename CType>
class CClass
{
CClass();
CType GetCClass();
}
And inside the wrapper project I have 2 enums and a class with a method:
public enum class AorBEnum
{
A = 0,
B = 1
};
public enum class CEnum
{
C = 0
};
void UseCode(TypeForAB ab, TypeForC c)
{
unknowntype a;
unknowntype b;
switch(ab)
{
case AorBEnum::A_TYPE:
a = AB<A>();
case AorBEnum::B_TYPE:
a = AB<B>();
}
switch(c)
{
case CEnum::C_TYPE:
b = CClass(C);
}
unknowntype vala = a.GetAB();
unknowntype valb = b.GetCClass();
}
What I am trying to do is create some objects using the parameters given to UseCode, then use methods from those objects.
Imagine I have a lot more classes and enums like these.
The question is: What can I use instead of unknowntype for it to work?