java知识回顾笔记(对象、反射、内省、实例、父类、构造方法、封装、泛型、super()、内部类、回调)

类&对象

在创建了一个类时,只声明但不赋值,其默认值为:
在这里插入图片描述
理解下图含义,即可理解对象和类:

在这里插入图片描述

实例

对象又被称为实例,实例变量被创建时,系统默认会赋值,例如:

Student student = new Student()
# student.name此时就有默认值

堆和栈

对象是存在堆内存中的,方法所需要的内存会在栈中分配,例如main()方法。
1.堆内存中存储对象以及实例变量
2.局部变量存放在栈里面
3.当new 一个对象时,例如Student s1=new Student()时(s1为局部变量),s1此时存储的为对象的堆地址,像s1这种存储了地址的变量有一个特殊的名字:引用
在这里插入图片描述
在这里插入图片描述

java执行堆栈画图【老杜版】

局部变量&成员变量

方法体外(class里)的变量叫成员变量、方法体内声明的变量叫局部变量
局部变量存放在栈内存中,成员变量也叫实例变量存放在堆内存
在这里插入图片描述

构造方法

构造方法又被称为:构造器、Constructor、构造函数
构造方法有两个作用:1.创建对象 2.给对象赋值

当new一个对象时,会自动运行一个无参数的构造方法,当用户没有自定义一个构造方法时,系统默认提供了一个无参数的构造方法

public class test {
    public static void main(String[] args){
        Student student = new Student();
}
}

Student.java

public class Student {
	String name;
    public Student(){
        System.out.println("execute!!!");
    }
}

知识回顾

封装

封装就是将public私有化

封装的主要作用:
1.保证内部结构安全
2.屏蔽复杂、暴露简单

方法名解析static

在方法体中声明的变量叫做局部变量
在方法体外声明的变量叫做成员变量
成员变量又分为:实例变量、静态变量,例如:

class VarTest{
//成员变量中的实例变量,可以new对象,所以会造成空指针异常
int i;
//成员变量中的静态变量,静态的,不会需要new对象,不会造成空指针异常
static int k;
}

静态方法:

public static void m1(){
}

那么我们什么时候使用static,什么时候不使用呢?根据上面提到的,成员变量中不使用static就是实例变量:

Class Chinese{
//身份证应该是实例变量,因为一个身份证对应一个对象
String idCard;
//国籍,国籍是一个类别人的特性,并不属与一个人的特性
//String Contry;
Static String Contry;
}

如果使用非static修饰,contry每次都会在内存中开拓一片空间,导致内存浪费
在这里插入图片描述
如果使用static修饰,contry会存放在方法区中,不会被新建到对象中
在这里插入图片描述
我们可以通过Chinese.Contry来实现调用Contry,但是不能直接调用Chinese.idCard。因为Contry是被static修饰的静态变量,被static修饰的内容都可以采用类名.进行访问

Class Chinese{
//身份证应该是实例变量,因为一个身份证对应一个对象
String idCard;
//国籍,国籍是一个类别人的特性,并不属与一个人的特性
//String Contry;
Static String Contry = "中国";
}

static: 都是修饰类相关的,所有static修饰的都可以采用类名.进行访问

反射

反射包:java.lang.refiect.*

java.lang核心包
java.util工具包
java.io io流包

反射的标志:

Class c1 = Class.forName("java.lang.String")  //c1代表了String.class文件,或者说代表了String类型

反射可以操作class文件,反射机制相关重要的类有:

java.lang.Class:代表整个字节码,代表一个类型
java.lang.reflect.Method:代表字节码中的方法字节码。代表类中的方法。
java.lang.reflect.Constructor:代表字节码中的构造方法字节码
java.lang.reflect.Field:代表字节码中的属性字节码
要先调用了Class,才能获得Method、Constructor、Field等

要操作一个类的字节码,需要首先获取到这个类的字节码,怎么获取到java.lang.Class实例?:

第一种:Class c = Class.forName(“完整类名带包名”);
第二种:Class c = 对象.getClass();
第三种:Class z =String.class; Class k =Data.class;

代码分析:
以下就是通过反射配合newInstance创建对象,c此时代表User.class这个文件或者说代表了这个类型

Class. c = Class.forName("com.test.java.bean.User");
Object obj = c.newInstance();

举例,通过反射调用runtime.exec弹计算器:

invoke是Method类中的一个方法。表示执行方法的调用
参数1.表示一个对象,要执行这个对象的方法
参数2.方法执行的参数

Runtime r = Runtime.getRuntime();
Class run = Runtime.getRuntime().getClass();
// 获取Runtime的exec方法
Method execMethod = run.getMethod("exec",String.class);
// 调用exec方法
execMethod.invoke(r,"calc");

通过反射给属性值赋值

Class c = Class.forName("com.java.test.Student"); 
Object obj = c.newInstance();
Field noFiled = c.getDeclaredField("password") //Student类中有一个String password;
noFiled.set(obj,2222)//给password设置值为2222
noFiled.get(obj)//读取password的值

//私有变量可以通过以下代码进行打破封装进行访问
noFiled.setAccessible(true)

在这里插入图片描述

通过反射调用指定参数类型的构造方法

Map map = TransformedMap.decorate(map, null, d);
Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
//AnnotationInvocationHandler类中有一个构造方法只接收(Class.class,Map.class)传入
Constructor ct = cls.getDeclaredConstructor(Class.class,Map.class);
ct.setAccessible(true);
//创建对象
Object o = ct.newInstance(Documented.class, map);

泛型

在下面这种情况时,it.next()该用哪种类型去接收?
在这里插入图片描述
使用泛型指定list中只能存储Animal类型的数据

list<Animal> myList = new ArrayList<Animal>();

因为Cat和Bird都是继承Animal的,所以这时候能够:

Cat c = new Cat();
Bird b = new Bird();
myList.add(c);
myList.add(b);

Iterator<Animal> it =myList.iterator();
while(it.hasNext()){
	Animal a = it.next();
	}

super()

当一个构造方法,存在super(),代表调用父类的无参构造方法,当存在super(123)表示调用父类有参数的构造方法:

class B extends A{
	super();
	super(123);
	public B(){
		System.out.println("B类无参构造方法!")
	}
}

匿名内部类+回调编程写法

回调编程: 通俗理解,callInContext方法内部定义了对.call的调用(接收一个Object参数,calllnContext内部实现调用了Object.call),而传入的对象类型ContextualCallable并且实现了call方法
匿名内部类: 即ContextualCallable只是一个接口,它没有显式的类名,而是在创建对象的同时定义和实现类。

public <T> T getInstance(final Class<T> type) {
    return this.callInContext(new ContextualCallable<T>() {
        public T call(InternalContext context) {
            return ContainerImpl.this.getInstance(type, context);
        }
    });
}

匿名内部类例子1:

public interface Greeting {
    void sayHello();
}
public class Main {
    public static void main(String[] args) {
        // 使用匿名内部类实现接口
        Greeting greeting = new Greeting() {
            public void sayHello() {
                System.out.println("Hello, world!");
            }
        };

        greeting.sayHello(); // 调用接口方法
    }
}

匿名内部类例子2(JavaAgent):
常规写法是使用implements,但是使用匿名内部类更具有封装性和灵活性

private static ClassFileTransformer createClassFileTransformer() {
        return new ClassFileTransformer() {
        @Override
        public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
                                    ProtectionDomain protectionDomain, byte[] classfileBuffer) {...}
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

向阳-Y.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值