static:静态的!①随着类的加载而加载;②共享~
static可以用来修饰:属性、方法、代码块、内部类
使用static修饰属性:静态变量(或类变量)
属性:按是否使用static修饰,又分为:静态属性 VS 非静态属性(实例变量)
非静态属性:我们创建了类的多个对象,每个对象都独立的拥有一套类中的非静态属性。当修改其中一个对象的静态变量,不会导致其中对象中同样的属性值的修改。静态变量:我们创建了类的多个对象,多个对象共享一个静态变量。当通过某一个对象修改静态变量时,会导致其他对象调用此静态变量时,是修改过了的。static修饰属性的其他说明:
静态变量随着类的加载而加载。可以通过”类.静态变量“的方式进行调用。
静态变量的加载要早于对象的创建。
由于类只会加载一次,则静态变量在内存中也只会存在一份:存在方法去的静态域中。
类变量 实例变量
类 yes no
对象 yes no
静态属性举例:System.out;Math.PI
使用static修饰方法:静态方法
随着类的加载而加载,可以通过”类.静态方法“的方式进行调用
静态方法 非静态方法
类 yes no
对象 yes yes
静态方法中,只能调用静态的方法或属性(比如main方法中能调用静态的方法和属性。)
非静态方法中,既可以调用非静态的方法或属性,也可以调用静态的方法或属性
static注意点:
在静态方法内,不能使用this关键字、super关键字(这是因为静态方法随类一起创建,而this和super都是对象)关于静态属性和静态方法的使用,要从生命周期的角度去理解:开发中,如何确认一个属性是否需要声明为static呢?
属性是可以被多个对象所共享的,不会随着对象的不同而不同的!类中的常量也常常声明为static开发中,如何确认一个方法是否需要声明为static呢?
操作静态属性的方法,通常设置为static的工具类中的方法,习惯上声明为static的。比如:Math、Arrays、Collections共享~
单例设计模式,就是采取一定方法保证在整个软件系统中,对某个类只有一个对象实例。
饿汉式: 缺点:对象加载时间过长优点:饿汉式是线程安全的 懒汉式: 优点:延迟对象的创建缺点:目前的写法,线程是不安全的——>到多线程内容时解决。要实例化一个对象的时候,再去实例化。
public class Order{ //1.私有化类的构造器 private Order(){ } //2.声明当前类的对象,没初始化 //4.要求此对象也必须声明为静态的 private static Order instance = null; //3.声明public、static的返回当前类对象的方法 public static Order getInstance(){ if(instance == null){ instance = new Order(); } return instance; } }类的成员:属性、方法、构造器、代码块、内部类
final可以用来修饰:类、方法、变量
final用来修饰一个类:此类不能够被其它类所继承final用来修饰方法:表示类不能够被重写final用来修饰变量:此时的变量就是一个常量,不可以重新赋值 static final 用来修饰属性,表示全局常量abstract可以用来修饰:类、方法
抽象类: 此类不能够实例化抽象类中一定由构造器,便于子类实例化时调用开发中,都会提供抽象类的子类,让子类对象实例化,完成相关操作 抽象方法: 抽象方法只有方法的声明,没有方法体{}包含抽象方法的类,一定是抽象类;反之抽象类中可以没有抽象方法若子类重写了父类中的抽象方法,此子类可以实例化若子类没有重写父类的抽象方法,那么子类必须为一个抽象类,不然报错。 public abstract class Vehicle{ public abstract double calcFuelEfficiency();//计算燃料效率的抽象方法 public abstract double calcTripDistance();//计算行驶距离的抽象方法 } public class Truck extends Vehicle{ @Override//重写计算卡车的燃料效率的具体方法 public double calcFuelEfficiency() { return 0; } @Override//重写计算卡车行驶距离的具体方法 public double calcTripDistance() { return 0; } }接口中定义的静态方法,只能通过接口来调用
通过实现类的对象,可以调用接口中的默认方法。
如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的默认方法,那子类在没重写此方法的情况下,默认调用的是父类中的同名同参数的方法。——>类优先原则
如果实现类实现了多个接口,而多个接口中定义了同名同参数的默认方法,那么在实现类没重写此方法的情况下,报错。——>接口冲突
如何在子类(或实现类)的方法中调用父类接口被重写的方法
当父类和父接口出现重名的属性,那么调用同名的属性必须做出选择,不然就报错! 可以使用Super.属性,调用父类中的同名属性。可以使用父接口名.属性,调用父接口中的同名属性。这是因为接口中的属性都是静态常量。 public void myMethod(){ method3();//调用自己定义的重写的方法 super.method3();//调用的是父类中声明的 //调用接口中的默认方法 CompareA.super.method3(); CompareB.super.method3(); }如果有些子类或实现类,只使用一次,那么去单独为其创建java文件也挺麻烦的,可以使用匿名内部类,去解决这一问题。
public class PlaneTest { public static void main(String[] args) { //如果子类只使用一次,那么可以创建匿名内部类,也就不用再创建一个子类单独的java文件 //不过和创建子类文件一样都要重写其内部的abstract的抽象方法。 //这体现了多态的性质,父类的对象指向子类。 Traffic t1 = new Traffic() { @Override public void transport() { System.out.println("t1...transport..."); } }; //多态,父类的对象,看运行时,是子类重写的方法。 t1.transport(); //接口也是同样的道理。 Fly fly = new Fly(){ @Override public void fly() { } }; } }Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类
成员内部类(静态、非静态)
一方面作为外部类的成员: 调用外部类的结构可以被static修饰可以被4种不同的权限修饰 另一方面,作为一个类: 类内可以定义属性、方法、构造器可以被final修饰,表示不可以被继承可以被abstract修饰局部内部类(方法内、代码块内)
注意点: 在局部内部类的方法中(比如:show如果调用局部内部类所声明的方法(比如:method)中的局部变量(比如:num)的话,要求此局部变量声明为final的。
public class InnerClassTest{ public void method(){ //局部变量 int num = 10; class AA{ public void show(){ //num = 20;//错误!!默认num为final的 System.out.println(num);//输出10 } } } }总结: 成员内部类和局部内部类,在编译以后,都会生成字节码文件。 格式:成员内部类:外部类$内部类名.class
局部内部类:外部类$数字 内部类名.class
测试类:
package www.atguigu.exer1; /** * @author:Ven * @date:2020/8/9 - 15:56 * @function: */ public class AccountTest { public static void main(String[] args) { Account account = new Account("112341", 2000); Account account1 = new Account(); Account.setRate(0.012); Account.setMinMoney(100); System.out.println(account); System.out.println(account1); System.out.println(account.getRate()); System.out.println(account.getMinMoney()); } }Account类
package www.atguigu.exer1; /** * @author:Ven * @date:2020/8/9 - 15:45 * @function: */ public class Account { private int id; private String pwd = "000000"; private double balance; private static double rate; private static double minMoney = 1.0; private static int init=1001; public Account() { id = init++; } public Account(String pwd, double balance) { this(); this.pwd = pwd; this.balance = balance; } public int getId() { return id; } public double getBalance() { return balance; } public static double getRate() { return rate; } public static double getMinMoney() { return minMoney; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } public static void setRate(double rate) { Account.rate = rate; } public static void setMinMoney(double minMoney) { Account.minMoney = minMoney; } @Override public String toString() { return "Account [id="+id+", pwd="+pwd+", balance="+balance+"]"; } }