Java 临时抱佛脚1
Java 临时抱佛脚
反射:RTTI 动态的获取对象属性
// 方法1 getClass from object Class a = obj.getClass(“ClassName”); // 方法2 Class.forName() Class a2 = Class.forName(“ClassName”);
Method m = a.getMethod(“MethodName”,null);
抽象类与接口
抽象类和接口的区别更多的体现在design上。因为Java不支持多继承,每个类都只能继承自一个基类,那么抽象类表示 的含义是 “is a",而接口表示的是附属属性“has a”,比如一个防盗门,门是它的基本属性,防盗是它的附加属性,那么 门应该作为抽象类存在,而防盗作为接口提供附加属性。
// 抽象类
abstract class A1{
abstract public void f1();
abstract public void f2();
}
// 接口
interface I1{
void f1();
void f2();
}
class A2 extends A1{
public void f1(){
System.out.println("F1");
}
public void f2(){
System.out.println("F2");
}
}
- 对象定义
Java的基本数据类型定义在栈上,对象定义在堆上。对象变量实际上是对于对象的引用(实际上Python有相同的概念), 因此在使用时要区分==和equals()
== 表示比较值, equals 表示比较引用
比如
// class A
A a1 = new A("123");
A a2 = new A("123");
A a3 = a1;
a1 == a3 // True
a1 == a2 // False
- 静态块
看下面这个例子
// case1
class B{
private static int count = 10;
static{
count = 20;
}
public void printCount(){
System.out.println(count);
}
}
// case2
class B{
static{
count = 20;
}
private static int count = 10;
public void printCount(){
System.out.println(count);
}
}
结果:
20 // case1
10 // case2
出现这样结果的原因在于,java静态变量的初始化就是在静态块中进行的,因此直接在变量定义时赋值和通过 静态块定义都会改变变量的值,最终的结果取决于它们的定义顺序。
另外,和C++一样,Java允许非静态函数中包含静态变量,反之不可,原因想想静态和非静态的编译时刻,静态函数中没有 this指针,因此无法了解具体在调用的是哪个对象的变量。
访问权限
Java的类只有public和包内两种访问权限。默认是包内,对于每个.java文件,最多只能有一个public类,因为每个
.java文件会被编译为.class,那么它的对外接口最多只能有一个。
abstract修饰的类:表示抽象类,用于后面的继承 (必须有子类) final修饰的类: 表示常量类,不可以被继承 (无子类)
final / finally / finalize
这看起来是java的一个经典议题,它们的相关性是。。它们长得很像。但从功能上讲,它们完成的功能完全不同
final :
与C++ const比较
1. 对于基本类型,可以认为二者是一致的 (似乎final可以用于call 非final的成员函数而const不可以)
2. 表示常量类
finally :
异常处理中必须要执行的操作,通常是文件/数据库的关闭等,但此函数的调用时间是由GC决定的,因此执行
时刻可能是任意的
finalize:
在垃圾回收时会调用的方法,值得注意的是,它本身并不会主动触发垃圾回收,实际上是在垃圾回收时负责
特殊的清理工作
- 垃圾回收
既然说到了垃圾回收,Java采用的回收机制主要有两种
1. mark and sweep : 一块空间,造成不连续,少量垃圾对象
2. stop and copy :两块内存空间,连续,对象拷贝
Java和C++区别 (杂)
- Java中的方法均定义在类内,不允许在类外定义方法
- Java没有作用域运算符::,所有操作用.表示
- Java的类定义没有分号结尾
- Java中只有公有继承,通过extends关键字声明;而implements关键字是声明接口继承用的;
- Java不直接支持多继承,可以用接口替代
- Java通过super显式调用基类构造器;
- final表示不可改变的,和const基本类似;
- private方法隐含就是final类型的;
- final参数表示变量无法在函数中修改
- final函数表示函数不能被重写
foreach遍历容器
int arr1[] = {1,3,5,2}; for (int element : arr1){ System.out.println(element); }
类型转换
String to int int a = Integer.parseInt(s); int to String String s = String.valueOf(a); // 其余类型类似 Integer是int的包装,int是基本类型,Integer是类
instanceOf 和 getClass
a instanceOf DerivedA 会判断a是不是DerivedA或者它的基类类型 a.getClass() == DerivedA.class 只判断a是不是DerivedA类型,不包括对于基类的判断
传值还是传引用
参见Python pass by Vlue
String和StringBuffer
String str = “”; str += “here”; 其实际的操作是str对象不可变,而是改变了str的指向,即此过程中,创建一个新的对象 StringBuffer sb = new StringBuffer(str); sb.append(“here”); str = sb.ToString() 因此String对于可变数组的效率比StringBuffer小非常多;