如果构造方法也被私有怎么办?
//构造方法私有,仅内部可以使用,在内部产生本类的实例化对象
private static Person person = new Person()
public static Person getPersonInstance(){
//实例方法中返回一个对象,返回值类型为这个类
return person
}
调用时:
//因为对象属性是static,是属于类的属性,所以使用它的方法getPersonInstance()也是static的,调用这个方法时,只能用类去调用
Person per = Person.getPersonInstance();
Person per2 = Person.getPersonInstance();
单例设计模式:
用堆、栈理解:栈中放的是变量名,堆中放的是对象,也就是new一次有一个地址,但是,new在了类中,所以堆中只有一个地址,在主方法中的per和per2都是指向堆中这一个地址的
封装(5点)
一、static关键字
1、static属性:全局属性,静态属性
2、static方法:类方法,可由类名称直接调用;非static声明的方法为普通方法,调用时用对象名去调用
JVM内存:
1、全局数据区:放static属性和代码定义的常量,不会被GC掉
2、栈内存空间:保存所有对象名称(即堆内存空间的引用地址),程序执行结束后即引用结束
3、堆内存空间:保存每个对象的具体属性内容及new的数据,若堆内数据无引用,jvm的gc线程依据回收策略则会回收掉
4、全局代码区:保存所有方法的二进制代码,而且是多个对象共享一个代码空间区域,不能被GC掉
注:
编译完成后,全局代码区就有数据了,但是全局数据区,栈内存空间以及堆内存空间,只有当新建一个对象的时候,才会有数据
问题:
非static方法调用static属性不报错
static方法调用非static属性报错??为什么?
1、调用非static方法的前提是,先实例化了一个对象,实例化对象后,对象的static属性在全局数据区有数据,非static属性在堆中有数据,此时再去调用static属性是可以调到的
2、系统编译完成后,static方法已经在全局代码区中了,而此时如果我去调非static属性,就要看它有没有,在什么情况下static属性会有呢?在实例化的时候才有,所以,如果static方法调用非static属性就会存在调不到数据的情况,系统是不允许的,所以会报错。
3、现有类,先有全局,才有对象。对象调全局的数据,全局的数据是肯定存在的,所以肯定可以调到;而全局调对象的属性,就会存在调不到的时候
利用static统计类被实例化了几次
在类中补充static属性count
private static int count = 0
public Person(){
count++;
}
public getCount(){
return count;
}
main中
per = new Person();
System.out.println(per.getCount())
二、匿名对象(没有变量名的对象)
例:new Person()
它只在堆中开辟了空间,未在栈中开辟空间;一般只用一次;当栈中达到回收标准时被GC掉
三、this
this代表当前类
this可以调用当前类的属性
this可以调用本类中的构造方法
构造方法可以是static吗?不可以把?new Person()时会在栈中存数据,若static了,实例化不了了,因为数据在全局数据区中了
1、构造方法在实例化对象时被自动调用的,即构造方法优先调用,故this调用构造方法必须也只能放在构造方法的首行
public Person(String name, int age){
this();
this.name=name;
this.age=age;
}
如果this()放在后面,传入参数后,初始化了属性值,又执行了this(),参数又没有了
2、this调用构造方法时一定要留一个构造方法作为出口,即程序中至少存在一个构造方法是不适用this调用其他构造方法的
构造方法调用构造方法,会一直调用不完的
四、内部类
类内部可以定义变量和方法,也可以定义类
1、类是由属性和方法组成的,内部类存在已经破坏了类的基本结构,内部类可访问外部类中的私有属性(原因:属性的作用范围是整个类,而内部类也在类中,所以内部类可以使用属性)
2、static内部类不能调用非static属性和方法(原因:非static属性和方法只有在实例化的时候在堆和栈中有数据)
3、调用内部类时,把它看成方法,调用方法时需要两步,①实例化一个对象;②使用对象.方法调用
内部类同样的两步,例:
①实例化:Outer out = new Outer();
②调用内部类:Outer.Innter in = out.new Inter(); //类型是内部类Outer.Innter,调用还是点,但是由于是内部类,所以要new一下内部类
五、代码块
1、普通代码块,类中方法里面的代码块
2、构造块,类中直接花括号中的代码块,实例化几次,执行几次
3、静态代码块,static花括号里面的代码块,只执行一次,优先于主方法执行
若在主类中也有静态代码块,则先执行静态代码块,再执行主方法
若在普通类中,先执行主类中的静态代码块(1次),再执行普通类中静态代码块(1次),再执行构造块,构造方法,普通代码块
继承
继承:在现有类基础上进行功能扩充,此种方式可快速开发出新的类,不需要写相同的程序代码,也是代码再利用的概念
1、子类可继承父类非封装的属性和方法,封装的属性,子类可以去调用set、get方法或构造方法解决
2、子类可以有自己的属性和方法
3、子类一次只能继承一个父类,不能同时继承多个父类,可多层继承
4、子类实例化之前首先调用父类的构造方法(对父类中的属性初始化),然后再调用子类自己的构造方法,余下的父类和子类的普通方法,由子类对象调用执行
方法的覆写(重写)
@override
1、子类定义了和父类同名的方法、参数类型、返回值类型必须也相同
2、子类覆写的方法不能拥有比父类更加严格的访问权限;private<default<public
3、当方法被覆写之后,子类对象调用的方法是被覆写后的方法
4、父类方法若是private,则子类不能覆写,因为没有继承到private方法
属性的覆写
构造方法的重载
@overload
在一个类中,类中方法名相同,参数类型或个数不同,对权限没要求
super
- 可以从子类中调用父类中的构造方法,普通方法,属性(没有封装的属性)
- super调用父类中指定的构造方法操作,与this用法一样,语句必须放在子类构造方法的首行
- 在子类构造方法中不能即用super调用父类构造方法,又用this调用子类构造方法,因为他们两个都要放首行,冲突
final(不能被修改)
- final声明的类不能被继承
- final声明的方法不能被子类覆写
- final申明的变量为常量,不能被修改
abstract(抽象)--------->>> 模板设计模式
- 包含一个抽象方法的类必须是抽象类
- 抽象方法只需声明,不需要实现
- 不能被private修饰,必须public修饰,否则子类不能实现
- 抽象方法可以是普通方法,也有自己的构造方法
- 抽象类必须被子类继承,子类必须重写类中所有的抽象类
- 抽象类不能被实例化
作用:当父类,当模板
接口interface
接口是java中的一种特殊类,是由全局常量和公共抽象方法组成
格式:
interface 接口名称{
全局常量;
抽象方法
}
注意:
1、接口继承接口
interface 接口A extends 接口B,接口C{
}
接口可一次性可继承多个接口,普通类只能一次继承一个类
2、普通类/抽象类实现接口
2.1、普通类实现接口
Class A implements 接口B,接口C{
重写所有接口的抽象方法
}
2.2、抽象类实现接口,接口不允许继承抽象类(原因:抽象类中可能有普通方法,接口一旦继承普通方法和属性就不符合接口了)
Class abstract A implements 接口B,接口C{
重写所有接口的抽象方法
}
一个子类可以同时实现多个接口(implements)子类必须要重写接口内的所有抽象方法,可以摆脱java中的单继承局限
3、子类同时继承抽象类和实现接口
格式:
Class 子类 extends 抽象类 implements 接口A,接口B{
重写抽象类以及接口中的所有抽象方法
}
问:抽象类实现接口需要重写接口里面的抽象方法吗?
如果抽象类和接口都可以使用,优先选择接口,可以避免单继承缺陷
多态
1、对象向上转型
抽象类A中有抽象方法print(),普通类B,普通类B继承接口A且重写了抽象方法print()
如何实例化一个抽象A对象(抽象类不能实例化,可以利用它的子类来进行实例化)
A a = new B(); //接口不能实例化,可以用子类来实例化
a.print() //a调用方法时,调用的是B中重写的,因为A中的print方法里面啥也没有,在B中才有具体的实现