一. 构造器
什么是构造器
所谓构造器就是在一个类的实例化之前必须要调用的方法,它和类的名字是一样的,每个类都有一个默认的无参的构造器。
public class Demo1 {
public Demo1(){}
}
注意,当类中已经有了构造器后,那么默认构造器会自动失效。
构造器的重载
当想用不同的方法去创建一个方法时,就需要用到构造器的重载
public class Demo1 {
int a;
public Demo1(){
System.out.println("无参构造器");
};
public Demo1(int a){
System.out.println("有参构造器");
this.a=a;
}
}
如何区分重载方法呢?
区分重载方法很简单,即每一个重载方法都有一个独一无二的参数列表
参数列表的不同体现在:
1. 声明的参数的个数不同
2. 声明的参数类型不同
3. 声明的参数顺序不同
4. 返回值不同也可(只在特定的语境下才可以)
注意,基本数据类型会在传入一个较小的数据类型的时候自动将它的的和数据类型提升一些,如byte转为short,short转为int,但是char有所不同,如果无法找到正好接受char的方法,那么就会直接将char提升到int类型。
如果传入的参数比较大的话,那么必须要通过强转来降低类型。
This关键字
使用this关键字的必要性
this关键字只可以使用在方法的内部,表示“调用方法的那个对象”的引用,也可以返回当前对象的引用,也可以将当前的对象传递给其他的方法。
class Demo2{
int i=0;
Demo2 incremnet(){
i++;
return this;
}
void print(){
System.out.println(this.i);
}
public static void main(String[] args) {
Demo2 demo2=new Demo2();
demo2.incremnet().incremnet().incremnet().print();
}
}
可以在一个构造器中调用另一个构造器
可以在一构造器之中调用另一个构造器,但是但是必须要注意两点:
1. 调用的构造器必须处于最顶端,否则会报错;
2. 除了构造器之外,严禁在其他的任何方法中调用构造器。
更加了解static关键字
将一个成员变量或者方法声明为静态变量或者静态方法,此时这个变量或者方法是属于类的,而不是属于某个具体的对象的,可以通过类名就直接去调用他们了。当然,一般对象的引用也可以引用他们。
其实,static方法就是在方法内没有this的方法,在static方法内不可以调用非static方法以及非static变量,但是反过来是可以的。
垃圾回收
关于垃圾回收,必须要明确这三点:
1. 对象可能不会被垃圾回收
2. 垃圾回收并不等于析构
3. 垃圾回收只和内存有关
构造器的初始化
构造器的最重要的作用就是进行初始化(尽管java已经有了足够的保障来保证初始化的进行,具体体现在:
1. 成员变量而言,基本数据类型未初始化,每个数据类型都有其自己的初始值。
2. 对象没有初始化,默认是null。)
对于静态数据的初始化而言,基本没什么不同,但是静态初始化只会在必须的时刻进行,如果不创建对象,也不引用对应的静态变量,那么静态初始化几乎不会进行。
这里,我们总结一下对象的创建过程(以一个dog类为例子)
1. 即使没有显示的使用static关键字,但是构造器实际上也是静态方法,因此,当首次创建类型为dog的对象,或者首次访问dog类的静态方法或者静态变量是,java解释器必须先根据类路径定位到dog.Class文件。
2. 然后载入Dog.class,有关静态初始化的所有操作都会进行,因此,静态初始化只会在class文件第一次加载的时候会进行一次。
3. 当用new Dog()创建对象的时候,会在堆上为dog对象分配足够的存储空间。
4. 这块存储空间会被清零,这样就会自动的为dog独享的所有基本的数据类型都设置成默认类型。
5. 执行所有出现在字段定义处的初始化动作。
6. 执行构造器,这里面会牵涉道很多动作,尤其是涉及到继承的时候。
{
将多个静态代码组成一个静态代码块,static{
int i=0;
System.out.println("静态初始化");
}
这段代码也仅仅只在第一次初始化类的时候执行一次,即第一次谁给生成一个实例化对象或者第一次访问这个类的静态数据成员。
既然有静态代码块,那么就要显示的代码快,如{
System.out.println("显示的初始化");
}
这个代码块实在构造器之前执行的。
}
数组的初始化
数组在java中是一个特殊的数据对象,它是一些具有相同数据类型的数据的集合,可以是基本数据类型,也可以是引用,定义一个数组的方式有一下三种类型:
1. Int []a=new int[num];//直接指定数组的大小
2. Int []a=new int[]{1,3,4,5,}//后面的逗号可选
3. Int []a=new int[]{1,2,4};
注意,一但数组被初始化了,那么它的长度就不可以改变了,它有一些方法,这里指出来。
1. Array.toString();//打印出数组的字符串形式;
2. Array.CopyOf()
3. 太多了,不举例了,自己去jdk文档看。
可变参数列表
class Demo3{
void f(int...num){
for(int o:num){
System.out.print(o+" ");
}
}
public static void main(String[] args) {
new Demo3().f(1,2,4);
}
}
当然,这里也可以不输入任何的参数(这样做有时候会造成误解),或者在前面加上其他的参数。
枚举类型
简单来说,就是一种新的新的数据类型,其实是一个类,并且有着自己的独特的方法而已。
enum spiciness{
ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN
}
for(spiciness o:spiciness.values()){
System.out.println(o);
}
其实,枚举类型更多的是用在switch语句中。
二、权限控制
每一个只有一个public类,若还有其他的类的话,对外界来说是不可见的,他们主要是为了主public类服务的。
访问修饰符
Public,protected,private。
1. 包访问权限
没有加任何访问修饰符的变量或者方法意味着对当前的包而言,他们是可以访问的,但是对于对于其他的包而言,他们是private的。
2. 接口访问权限
使用了public关键字,也就意味着后面紧跟着的成员对自己和每个人都是可用的
3. Private:无法访问
即除了包涵该成员的类之外,其他任何的类都无法访问这个成员。
4. Protected :继承访问权限
包含了包访问权限的同时,只对自己的子类提供访问权限。
修饰符 全局 子类 包内 本类
使用权限修饰符的目的是为了具体实现的隐藏,其实就是为了封装
科普:单例模式
一、单例模式定义:
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。
二、单例模式特点:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
单例模式保证了全局对象的唯一性,比如系统启动读取配置文件就需要单例保证配置的一致性。
三、单例模式的创建。这里介绍两种创建方式,
1.饿汉式单例(立即加载方式)
// 饿汉式单例publicclass Singleton1 {
// 私有构造private Singleton1() {}
privatestaticSingleton1 single =new Singleton1();
// 静态工厂方法publicstatic Singleton1 getInstance() {
return single;
}
}
2.懒汉式单例(延迟加载方式)
publicclass Singleton3 {
// 私有构造private Singleton3() {}
privatestaticSingleton3 single =null;
publicstatic Singleton3 getInstance() {
// 等同于 synchronized public static Singleton3 getInstance()synchronized(Singleton3.class){
// 注意:里面的判断是一定要加的,否则出现线程安全问题if(single ==null){
single =new Singleton3();
}
}
return single;
}
}