static关键字
-
1.static:静态的
-
2.static可以用来修饰:属性、方法、代码块、内部类
-
3.使用static修饰属性:静态变量(或类变量)
-
3.1 属性,按是否使用static修饰,又分为:静态属性 vs 非静态属性(实例变量)
-
3.2 static修饰属性的其他说明:
- ① 静态变量随着类的加载而加载。可以通过"类.静态变量"的方式进行调用
- ② 静态变量的加载要早于对象的创建。
- ③ 由于类只会加载一次,则静态变量在内存中也只会存在一份:存在方法区的静态域中。
-
3.3 静态属性举例:System.out; Math.PI;
类变量 实例变量 类 yes no 对象 yes yes
-
-
4.使用static修饰方法:静态方法
静态方法 非静态方法啊 类 yes no 对象 yes yes - ② 静态方法中,只能调用静态的方法或属性;非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性
-
5.static注意点:
- 5.1在静态的方法内,不能使用this关键字、super关键字
- 5.2关于静态属性和静态方法的使用,大家都从生命周期的角度去理解。
-
6.开发中,如何确定一个属性是否要声明为static的?
-
7.开发中,如何确定一个方法是否要声明为static的?
单例设计模式
- 单例设计模式:
- 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例。
- 饿汉式:
- 坏处:对象加载时间过长。 //上来就new好对象,可能还不急着用,占用内存
- 好处:饿汉式是线程安全的
- 懒汉式:
- 好处:延迟对象的创建。
- 目前的写法坏处:线程不安全。—>到多线程内容时,再修改
饿汉式 //比较饿,上来就有吃的(上来就new好)
public class SingletonTest1 {
public static void main(String[] args) {
Bank bank1 = Bank.getInstance();
Bank bank2 = Bank.getInstance();
System.out.println(bank1 == bank2); } }
class Bank{
//1.私有化类的构造器 为了避免在类外面造对象
private Bank(){
}
//2.内部创建静态的类的对象
private static Bank instance = new Bank();
//3.提供公共的静态的方法,返回类的对象
public static Bank getInstance(){
return instance; } }
懒汉式 //比较懒,不得不上才上
public class SingletonTest2 {
public static void main(String[] args) {
Order order1 = Order.getInstance();
Order order2 = Order.getInstance();
System.out.println(order1 == order2); } }
class Order{
//1.私有化类的构造器 为了避免在类外面造对象
private Order(){
}
//2.内部声明静态的类的对象,没有初始化
private static Order instance = null;
//3.声明public、static的返回当前类对象的方法
public static Order getInstance(){
if(instance == null){
instance = new Order();
}
return instance; } }
main()方法
- main()方法的使用说明:
- 1.main()方法作为程序的入口
- 2.main()方法也是一个普通的静态方法
- 3.main()方法可以作为我们与控制台交互的方式。(之前:使用Scanner)
- 3.1 点击Run下的Edit Configurations
- 3.2 配置Program arguments选项,就可以在idea中传入参数,Apply后按OK就可以。
代码块
-
- 代码块的作用:用来初始化类、对象
-
- 代码块如果有修饰的话,只能使用static
-
- 分类:静态代码块 vs 非静态代码块
-
4.静态代码块
-
5.非静态代码块
-
{ System.out.println("hello"); }
-
内部可以有输出语句
-
随着对象的创建而执行
-
每创建一个对象,就执行一次非静态代码块
-
作用:可以在创建对象时,对对象的属性等进行初始化
-
如果一个类中定义了多个非静态代码块,则按照声明的先后顺序执行
-
非静态代码块内可以调用静态的属性、静态的方法,或非静态的属性、非静态的方法
-
执行顺序
- 对属性可以赋值的位置:
- ①默认初始化
- ②显式初始化/⑤在代码块中赋值 (那个写前面,那个先执行)
- ③构造器中初始化
- ④有了对象以后,可以通过"对象.属性"或"对象.方法"的方式,进行赋值
- 执行的先后顺序:① - ② / ⑤ - ③ - ④
final关键字
- 1.final可以用来修饰的结构:类、方法、变量
- 2.final 用来修饰一个类:此类不能被其他类所继承。
- 比如:String类、System类、StringBuffer类
- 3.final 用来修饰方法:表明此方法不可以被重写
- 比如:Object类中getClass();
- 4.final 用来修饰变量:此时的"变量"就称为是一个常量
- 4.1 final修饰属性:可以考虑赋值的位置有:显式初始化、代码块中初始化、构造器中初始化
- 4.2 final修饰局部变量:
-
尤其是使用[final修饰形参]()时,表明此形参是一个常量。当我们调用此方法时,给常量形参赋一个实参。一旦赋值以后,就只能在方法体内使用此形参,但不能进行重新赋值。
-
- final属性必须保证能够被赋值
- static final 用来修饰属性:全局常量
抽象类与抽象方法
- abstract关键字的使用
- 1.abstract可以用来修饰的结构:类、方法
- abstract修饰类:抽象类
-
此类[不能实例化]()
-
抽象类中一定有构造器,便于子类实例化时调用(涉及:[子类对象实例化的全过程]())
-
开发中,都会提供抽象类的子类,让子类对象实例化,完成相关的操作
-
- abstract修饰方法:抽象方法
-
抽象方法[只有方法的声明,没有方法体]()
-
包含抽象方法的类,一定是一个抽象类。反之,抽象类中可以没有抽象方法的。
-
若子类重写了父类中的所有的抽象方法后,此子类方可实例化
-
若子类没有重写父类中的所有的抽象方法,则此子类也是一个抽象类,需要使用abstract修饰
-
- abstract修饰类:抽象类
abstract使用上的注意点:
- 1.abstract不能用来修饰:属性、构造器等结构
- 2.abstract不能用来修饰私有方法、静态方法、final的方法、final的类
抽象类的匿名子类
//创建了匿名子类的对象:p (子类没有名)
Person p = new Person(){
@Override //子类重写抽象父类的全部抽象方法
public void eat() {
System.out.println("吃东西");
}
@Override
public void breath() {
System.out.println("好好呼吸");
}
};
匿名子类的匿名对象
//创建匿名子类的匿名对象
method1(new Person(){
@Override
public void eat() {
System.out.println("吃好吃东西");
}
@Override
public void breath() {
System.out.println("好好呼吸新鲜空气");
}
});
接口
-
1.接口使用interface来定义
-
2.Java中,接口和类是并列的两个结构
-
3.如何定义接口:定义接口中的成员
-
- 接口中不能定义构造器的!意味着接口不可以实例化
-
- java开发中,接口通过让类去实现(implements)的方式来使用.
- 5.1如果实现类覆盖了接口中的所有抽象方法,则此实现类就可以实例化
- 5.2如果实现类没有覆盖接口中所有的抽象方法,则此实现类仍为一个抽象类
-
6.Java类可以实现多个接口 —>弥补了Java单继承性的局限性
- 格式:class AA extends BB implements CC,DD,EE
-
8.接口的具体使用,体现多态性 //接口不能实例化
-
9.接口,实际上可以看做是一种规范
接口匿名实现类
class Computer{
public void transferData(USB usb){//USB usb = new Flash();
usb.start();
System.out.println("具体传输数据的细节");
usb.stop(); } }
interface USB{
//常量:定义了长、宽、最大最小的传输速度等
void start();
void stop(); }
class Flash implements USB{
@Override
public void start() {
System.out.println("U盘开启工作"); }
@Override
public void stop() {
System.out.println("U盘结束工作"); } }
class Printer implements USB{
@Override
public void start() {
System.out.println("打印机开启工作"); }
@Override
public void stop() {
System.out.println("打印机结束工作"); } }
/*************************************************************/
public class USBTest {
public static void main(String[] args) {
Computer com = new Computer();
//1.创建了接口的非匿名实现类的非匿名对象
Flash flash = new Flash();
com.transferData(flash);
//2. 创建了接口的非匿名实现类的匿名对象
com.transferData(new Printer());
//3. 创建了接口的匿名实现类的非匿名对象
USB phone = new USB(){
@Override
public void start() {
System.out.println("手机开始工作");
}
@Override
public void stop() {
System.out.println("手机结束工作");
}
};
com.transferData(phone);
//4. 创建了接口的匿名实现类的匿名对象
com.transferData(new USB(){
@Override
public void start() {
System.out.println("mp3开始工作");
}
@Override
public void stop() {
System.out.println("mp3结束工作");
}
});
}
}
接口应用(代理、工厂)
工厂模式:实现了创建者与调用者的分离,即将创建对象的具体过程屏蔽隔离 起来,达到提高灵活性的目的。
代理模式
public class NetWorkTest {
public static void main(String[] args) {
Server server = new Server();
// server.browse();
ProxyServer proxyServer = new ProxyServer(server);
proxyServer.browse(); } }
//接口
interface NetWork{
public void browse(); }
//被代理类
class Server implements NetWork{
@Override
public void browse() {
System.out.println("真实的服务器访问网络"); } }
//代理类
class ProxyServer implements NetWork{
private NetWork work;
public ProxyServer(NetWork work){
this.work = work;
}
public void check(){ //代理类检查
System.out.println("联网之前的检查工作");
}
@Override
public void browse() {
check();
work.browse(); } }
工厂设计模式
简单工厂模式 //增加新产品,不修改代码的话,是无法拓展的,违反开闭原则(对扩展开放,对修改封闭)
interface Car {
void run();
}
class Audi implements Car {
public void run() {
System.out.println("奥迪在跑");
}
}
class BYD implements Car {
public void run() {
System.out.println("比亚迪在跑");
}
//工厂类
class CarFactory {
//方式一
public static Car getCar(String type) {
if ("奥迪".equals(type)) {
return new Audi();
} else if ("比亚迪".equals(type)) {
return new BYD();
} else {
return null;
}
}
//方式二
public static Car getAudi() {
return new Audi();
}
public static Car getByd() {
return new BYD();
}
}//添加新产品只能修改CarFactory工厂类,修改工厂类中的判断语句
public class Client02 {
public static void main(String[] args) {
Car a = CarFactory.getCar("奥迪");
a.run();
Car b = CarFactory.getCar("比亚迪");
b.run();
}
}
工厂方法模式 //增加新产品时,独立的去添加 (工厂模式有一组实现了相同接口的工厂类)
interface Car{
void run();
}
class Audi implements Car{
public void run() {
System.out.println("奥迪在跑");
}
}
class BYD implements Car{
public void run() {
System.out.println("比亚迪在跑");
}
} //这上面和简单工厂模式都一样
//工厂接口
interface Factory{ //不再使用类来设计工厂,使用接口设计工厂
Car getCar(); //设计抽象方法返回car,返回什么car就看实现类
}
//两个工厂类
class AudiFactory implements Factory{
public Audi getCar(){
return new Audi();
}
}
class BydFactory implements Factory{
public BYD getCar(){
return new BYD();
}
}
//添加新产品car继续添加实现类就可以
public class Client {
public static void main(String[] args) {
Car a = new AudiFactory().getCar();
Car b = new BydFactory().getCar();
a.run();
b.run();
}
}
简单工厂模式与工厂方法模式**没有真正的避免了代码的改动。在简单工厂模 式中,新产品的加入要修改工厂角色中的判断语句;而在工厂方法模式中,要么 将判断逻辑留在抽象工厂角色中,要么在客户程序中将具体工厂角色写死(就像 上面的例子一样)。而且产品对象创建条件的改变必然会引起工厂角色的修改。 面对这种情况,Java 的反射机制**与配置文件的巧妙结合突破了限制——这在 Spring 中完美的体现了出来。
接口 面试题
interface A {
int x = 0;
}
class B {
int x = 1;
}
class C extends B implements A {
public void pX() {
//编译不通过。因为x是不明确的; 接口和类是并列的两个结构
// System.out.println(x);
System.out.println(super.x);//1
System.out.println(A.x);//0
}
public static void main(String[] args) {
new C().pX();
}
}
内部类
- 类的内部成员之五:内部类
-
- Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类
- 2.内部类的分类:成员内部类(静态、非静态) vs 局部内部类(方法内、代码块内、构造器内)
成员内部类
-
- 如何实例化成员内部类的对象
//创建Dog实例(静态的成员内部类):
Person.Dog dog = new Person.Dog(); //Dog是Person的内部类
-
- 如何在成员内部类中区分调用外部类的结构 //遇到同名结构
System.out.println(name); //方法本身形参
System.out.println(this.name); //方法所属内部类的属性
System.out.println(Person.this.name); //方法所属内部类所属外部类的属性
局部内部类
- 在局部内部类的方法中(比如:show)如果调用局部内部类所属方法(比如:method)中的局部变量(比如:num)
public void method(){ // 方法内创建一个局部内部类
//局部变量
int num = 10; //方法属性
class AA{
public void show(){ //局部内部类的方法
// num = 20; //方法属性必须是final,不能修改值
System.out.println(num);
}
}
}