Java学习笔记2
程序入口:public static void main(String[ ] args)
main()函数被定义为public和static
static:静态方法,保存在静态存储区,无需实例化对象,就可以直接访问
public:权限修饰符,表示任何类和对象都可以访问这个方法。
void:没有返回值
此外需要注意,如果main所在的类里面还有static代码块,那么main里面的代码一定是最后的执行的。
抽象方法和抽象类
java的抽象类和c++里的抽象类很像,例子如下:
/**
* 车子类
*/
public abstract class Car {
public abstract void run();
}
/**
* 自行车
*/
class Bicycle extends Car{
@Override
public void run() {
System.out.println("人踩着跑。。。");
}
}
/***
* 汽车
*/
class Automobile extends Car{
@Override
public void run() {
System.out.println("发动机驱动跑。。。");
}
}
抽象方法的特点:
1、从上面的例子中我们可以看到抽象方法跟普通方法是有区别的,它没有自己的主体(没有{}包起来的
业务逻辑),跟接口中的方法有点类似。所以我们没法直接调用抽象方法
2、抽象方法不能用private修饰,因为抽象方法必须被子类实现(覆写),而private权限对于子类来
说是不能访问的,所以就会产生矛盾
3、抽象方法也不能用static修饰,试想一下,如果用static修饰了,那么我们可以直接通过类名调
用,而抽象方法压根就没有主体,没有任何业务逻辑,这样就毫无意义了。
抽象类
1、用abstract关键字来表达的类,其表达形式为:(public)abstract class 类名{}
2、抽象类不能被实例化,也就是说我们没法直接new 一个抽象类。抽象类本身就代表了一个类型,无法
确定为一个具体的对象,所以不能实例化就合乎情理了,只能有它的继承类实例化。
3、抽象类虽然不能被实例化,但有自己的构造方法
4、抽象类与接口(interface)有很大的不同之处,接口中不能有实例方法去实现业务逻辑,而抽象类
中可以有实例方法,并实现业务逻辑,比如我们可以在抽象类中创建和销毁一个线程池。
5、抽象类不能使用final关键字修饰,因为final修饰的类是无法被继承,而对于抽象类来说就是
需要通过继承去实现抽象方法,这又会产生矛盾。
java中的初始化操作(初始化的意思就是分配内存空间然后给个初值)
注意:在调用类的构造函数创造类的实例化对象之前,会先完成所有类成员的初始化操作;初始化操作优先级遵循原则如下:
1、静态对象(包括静态变量和静态代码块)优于非静态对象(其中静态对象只初始化一次(如果一个类里面有两个static的代码段是一样的,只会执行一次),但是非静态对象可能初始化很多次)
2、父类优先于子类
3、按照成员变量的定义顺序完成初始化
总结起来:父类静态变量->父类静态代码块->子类静态变量->子类静态代码块->父类非静态变量->父类非静态代码块(这里需要注意,先执行不属于任何成员函数的代码块)->父类构造函数->子类非静态变量->子类非静态代码->子类构造函数
(总结一下就是静态先于非静态;变量优于代码块,代码块优于构造函数)
这个考点就是给一段关于继承的代码,其中那些部分先执行,哪些部分后执行。
java中的作用域
java中的变量包括:成员变量、静态变量、局部变量(没有全局变量)
成员变量:它的生命周期和被实例化的对象的生命周期一样,他的使用是通过实例化的对象来实现的。
从强到弱:public >protected > default > private
可以这样理解:protected可以理解为保护别人的人,这样的人更好;default为一般的人,这样的人次之;private为自私的人,这样的人最差。
注意只有成员变量才需要用到这些修饰符;局部变量不需要,因为局部变量根本不存在子类和其他package这样的问题。而修饰类则只有public、abstract或final
静态变量:虽然java里面没有全局变量,但是它的静态变量可以当做是全局变量。它被所有类的实例共享,只要类被加载,JVM就会给他分配空间。通过类名.变量名来访问
局部变量:作用域为包含他的花括弧以内
一个java文件里面有多个类
一个java文件可以定义多个类,但是只能有一个类被public修饰,并且文件名要和这个类名相同。而如果没有public,则文件名字可以选择任意一个类名。
构造函数constructor(作用是实例化时初始化对象的成员变量)
1、如果没写构造函数会自动提供一个没有参数的默认的构造函数,里面什么都不执行。
2、在new之后自动调用,其名称和类名相同,但是没有返回值(因此连void也不需要加)
3、构造函数不能被继承,因此不能被覆盖(overide)。但是可以重载;因此,在父类没有提供无参数的构造函数时,子类必须显式地调用父类的构造函数;而如果父类提供了无参的构造函数,那么子类无需显式调用父类构造函数。
4、而如果子类与父类都没有定义构造函数的话,编译器会自动给他们都生成一个默认的无参构造函数。
5、注意类里面的普通方法是可以和构造函数一个名称的。区别就是构造函数无返回值,不需要加void,但是普通方法如果没有返回值需要加void。
java中的接口interface
c++里面有多继承,也就是一个类可以同时有多个父类,而java不支持多继承,只可以单继承。但是利用接口可以实现多继承的效果。
首先解释一下接口(可以理解为100%的抽象类):
官方解释:Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
我的解释:接口可以理解为一种特殊的类,里面全部是由全局常量和公共的抽象方法所组成。接口是解决Java无法使用多继承的一种手段,但是接口在实际中更多的作用是制定标准的。或者我们可以直接把接口理解为100%的抽象类,既接口中的方法必须全部是抽象方法,一般的抽象类里面可以存在非抽象方法(也就是有具体实现的)。(JDK1.8之前可以这样理解),因为里面的都是没有具体实现的,需要继承该接口的类来实现,因此里面所有的常量值默认使用public static final来修饰,其他成员的作用域都是public(不能为protected,dafault,private)。
所以呢,因为一个类可以implements(实现)很多接口,也就实现了继承很多父类。
此外,也会存在没有任何抽象方法的接口,这种接口被称作标志接口。因此这种接口对于实现它的类没有任何要求,仅仅充当一个标志的作业。java类库里面已存在的标志接口为Cloneable,Serializable等。我们使用instanceof来判断实例对象的类型是否实现了一个给定的标志接口。用来判断实现的是不是这个接口
4.12
java中的clone
在java中取消了指针的概念,因此在编程中忽略了对象和引用的区别。
作为参数传递的时候,如果参数是是一个类的对象,那么这种传递是“引用传递”(用=来赋值时也是引用传递);如果参数是基本的数据类型(int ,char等等)那么是“按值传递”(传递的是参数的复制体)
如果像下面这样:
对b修改了,a也会修改,但是有时候互相创建一个与a相同状态的b,但是对b的修改不会影响a,这时就需要clone
为什么可以使用clone呢?因为java里面所有的类都默认继承自Object类,这个类提供了clone方法。而这个clone返回的就是一个对象的复制,而不是引用。
使用方法:
1、首先这个类需要继承Cloneable接口,这个接口是一个标志接口(上面的接口里面提到了,里面没有任何抽象方法)。
2、重写Object类里面的clone方法。然后在clone方法里面调用super.clone()
3、把浅复制的引用指向原型对象新的克隆体。(原型对象新的克隆体表示的就是super.clone( );浅复制有两种实现方式,一个是clone,一个是通过拷贝构造函数(所谓的拷贝构造构造函数实际上是一种对于构造函数的重载,里面的参数是这个类的对象))
浅复制和深复制
首先区分一下:
1、浅复制,或者说浅拷贝:
①对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。
②对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。
总而言之,浅拷贝仅仅复制它所拷贝的对象,不复制他引用的对象
2、深复制,或者说深拷贝:
深拷贝对引用数据类型的成员变量的对象图中所有的对象都开辟了内存空间,进行复制。而浅拷贝只是传递地址指向,新的对象并没有对引用数据类型创建内存空间。总而言之,深拷贝把复制对象的引用的对象都复制了一遍。
用图表表示:
因此,如果类里面只有基本的数据类型,使用之前的提到的supr.clone方法就可以了,但是如果类里面包含一些对象,则要用到深复制。方法为:接着上面的代码后面对非基本数据类型(即其他类的对象)也调用clone().
因此,如果类里面还有对象,我们还需要对这些对象完成深复制
反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够获取这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取类信息以及动态调用对象内容就称为java语言的反射机制。(也就是可以动态的获得类的信息)
反射的作用:
- 在运行时判断任意一个对象所属的类;
- 在运行时构造任意一个类的对象;
- 在运行时判断任意一个类所具有的成员变量和方法;
- 在运行时调用任意一个对象的方法;
总结来说,就是可以判断任意一个对象是否包含某个信息(所属的类,包含的属性、方法),以及任意构建对象,任意调用方法。
反射的使用方法就是获取class类,获取方法有三种:
Class.forName(String className)、className.class、实例对象.getClass()
使用方法:
(获得类名,创建这个类的实例)
package作用
1、提供一个命名空间,使得多个package里面可以存在相同的类名。
2、对于大项目进行分类
包由一组类和接口组成
上一篇: 关于获取input type='file'的大小疑点
下一篇: 凡有SQL查询的地方都市有个注意