类变量和方法,main方法,final,抽象类,接口
类变量和类方法
1:类变量
1:类变量的内存布局
在jdk的不同版本中,有的人说类变量存储在静态域中,有的人说类存储在堆中,至于类真正储存在哪里跟jdk的版本有关,不管我们记住一点static变量是对象共享的。不管static变量在哪里我们应该有这样的共识,1:static变量是所有对象共享的,static变量在类加载的时候就生成了。
2:定义类变量和访问类对象的2种方式
- 定义类变量:
1:访问修饰符 static 数据类型 变量名;[推荐]
2:static 访问修饰符 数据类型 变量名;
- 访问类变量
1:对象名.类变量名
2:类名.变量名(推荐)
3:类变量名的细节问题:
-
类变量和实体变量的区别:
类变量是属于类的,实体变量是属于对象的,类变量是该类的所有对象都共享的,实体变量是每个对象独享的。 -
类变量的访问也遵守访问权限
-
类变量的生命周倜随着类的创建而创建,随着类的销毁而结束
-
只要类加载了就会创建类变量,即使没有创建对象,因为类变量随着类的加载而创建。
2:类方法
1:定义类方法和访问类方法的2种变量
- 定义类方法
访问修饰符 static 数据返回类型 方法名() {} 推荐
static 访问修饰符 数据返回类型 方法名() {} 推荐
- 类方法的调用
1:类名.方法名(推荐)
2:对象名.方法名
2:类方法的细节问题
- 类方法和普通方法都是随着类的加载而加载,将结构信息储存在方法,类方法中无this的参数,普通方法中隐含着this参数
- 普通方法和对象有关,需要通过对象名调用,不能通过类名调用
- 类方法中不能使用和对象有关的关键字,比如this,super
- 类方法只能访问静态方法和静态变量(访问非静态,需要new对象)
- 成员方法既可以访问非静态成员,也可以访问静态成员
理解main方法语法
1:注意的细节
- 解释main方法的形式 :public static void main (String [] args){ }
- main方法时虚拟机调用
- java虚拟机调用main方法时,该方法必须是public修饰
- java虚拟机在执行main方法时候不必创建对象,所有是static修饰
- 该方法接受String类型的数组参数,该数组保存执行java命令传递给所有运行的类的参数
2:用doc给main方法传参
3:用idea传参
final关键字
1:final的用法
-
final中文意思是最终的
-
final可以修饰方法,类,属性,局部变量
-
当局部变量不想被修改的时候可以用final
-
当属性不想被修改的时候可以用final
-
当类不想被继承的时候可以用final
-
当不希望父类的某个方法被子类覆盖/重写(override)时,可以用fianl关键字修饰(修饰访问符 和 final 返回 类型 方法名)
-
演示:
public class Fianl01 {
public static void main(String[] args) {
E e = new E();
//e.TAX_RATE = 0.09;
}
}
//如果我们要求 A 类不能被其他类继承
//可以使用 final 修饰 A 类
final class A { }
//class B extends A {}
class C {
//如果我们要求 hi 不能被子类重写
//可以使用 final 修饰 hi 方法
public final void hi() {}
}
class D extends C {
// @Override
// public void hi() {
// System.out.println("重写了 C 类的 hi 方法..");
// }
}
//当不希望类的的某个属性的值被修改,可以用 final 修饰
class E {
public final double TAX_RATE = 0.08;//常量
}
//当不希望某个局部变量被修改,可以使用 final 修饰
class F {
public void cry() {
//这时,NUM 也称为 局部常量
final double NUM = 0.01;
//NUM = 0.9;
System.out.println("NUM=" + NUM);
}
}
2:注意细节
- final修饰的属性又叫常量,一般用大写字母来描述XX_XX_XX
- final修饰的属性在定义时,必须给赋初值,并且以后都不能修改赋值可以在一下三种情况中:1,定义时候直接赋值,2:代码块中,3:构造器中
- 如果final修饰的属性是静态的,不能放在代码块中赋值
- final类不能继承,但是可以实例化对象
- 如果类不是final类,但是含有final方法,虽然方法不能被重现但是可以被继承
- 类已经是final类了,没必要给方法再加final了
- final不能修饰构造方法
- fianl和static往往搭配使用,效率更高,不会导致类加载,底层编译器做了优化处理
- 包装类,String也是fiinal类
- 演示:
public class Test{
public static void main(String[] args) {
CC cc = new CC();
new EE().cal();
}
}
class AA {
/*
1. 定义时:如 public final double TAX_RATE=0.08;
2. 在构造器中
3. 在代码块中
*/
public final double TAX_RATE = 0.08;//1.定义时赋值
public final double TAX_RATE2 ;
public final double TAX_RATE3 ;
public AA() {//构造器中赋值
TAX_RATE2 = 1.1;
}
{//在代码块赋值
TAX_RATE3 = 8.8;
}
}
class BB {
/*
如果 final 修饰的属性是静态的,则初始化的位置只能是
1 定义时 2 在静态代码块 不能在构造器中赋值。
*/
public static final double TAX_RATE = 99.9;
public static final double TAX_RATE2 ;
static {
TAX_RATE2 = 3.3;
}
}
//final 类不能继承,但是可以实例化对象
final class CC { }
//如果类不是 final 类,但是含有 final 方法,则该方法虽然不能重写,但是可以被继承
//即,仍然遵守继承的机制.
class DD {
public final void cal() {
System.out.println("cal()方法");
}
}
class EE extends DD { }
public class Test {
public static void main(String[] args) {
System.out.println(BBB.num);
//包装类,String 是 final 类,不能被继承
}
}
//final 和 static 往往搭配使用,效率更高,不会导致类加载.底层编译器做了优化处理
class BBB {
public final static int num = 10000;
static {
System.out.println("BBB 静态代码块被执行");
}
}
final class AAA{
//一般来说,如果一个类已经是 final 类了,就没有必要再将方法修饰成 final 方法
//public final void cry() {}
}
抽象类
1:为什么要有抽象类
- 我们假设一个场景,当父类的一些方法不能确定是,就可以考虑用抽象类。比如我们要定义一个动物类,这个类中有吃这个动作,但是我们不知道用什么吃,人会用筷子,动物用的是嘴,给这个动物类实现这个吃的方法是没有意义的,这时候我们就可以把吃这个方法定义为抽象方法
2:抽象类的介绍
- 用abstract关键字修饰一个类的时,这个类就是抽象类
- 用abstract关键词修饰一个方法时,这个方法就是抽象方法
- 抽象类的价值更多作用在于设计,设计者设计号后,让子类继承并实现抽象类
- 抽象类,是面试官比较爱问的知识点,再框架和设计模式使用比较多‘
3:抽象类使用的注意事项
- 抽象类不能被实例化
- 抽象类不一定有抽象方法,有抽象方法一定是抽象类。
- abstract只能修饰类和方法,不能修饰属性和其他的
- 抽象类本质还是类,可以拥有类可以拥有的成员(属性,方法,非抽象方法。。。。)
- 抽象方法没有主体
- 如果一个类继承了抽象类,则它必须实现抽象类的是所有抽象方法,除非这个类也是抽象类
public class AbstractDetail01 {
public static void main(String[] args) {
//抽象类,不能被实例化
//new A();
}
}
//抽象类不一定要包含 abstract 方法。也就是说,抽象类可以没有 abstract 方法
//,还可以有实现的方法。
abstract class A {
public void hi() {
System.out.println("hi");
}
}
//一旦类包含了 abstract 方法,则这个类必须声明为 abstract
abstract class B {
public abstract void hi();
}
//abstract 只能修饰类和方法,不能修饰属性和其它的
class C {
// public abstract int n1 = 1;
}
- 抽象方法不能被private,final,static修饰,因为这些关键字都于重写相违背
模板设计模式
- 抽象类体现的是一种模板模式设计,抽象类作为多个在子类通用的模板,子类在抽象类的基础上进行扩展修改,但是子类总体上保留抽象类的行为方式
- 解决的问题:
接口
1:接口的基本介绍
- 接口就是给出一些没有实现的方法,封装到一起,到某个类要使用的时候,再根据具体的情况把这谢谢方法写出来。
- 语法:
inferface 接口名 {
//属性
//抽象方法
}
class 类名 implements 接口 {
自己属性;
自己方法;
必须实现接口的抽象方法
}
- 接口是更抽象的抽象方法,在jdk1.7之前,接口里的所有方法都没有方法体。接口体现了程序的设计的多态和高内聚低偶合的设计思想,在jdk8.0后接口类可以有静态方法,默认方法,也就是说接口种可以有方法的具体实现。
2:注意细节
- 接口不能被实例化
- 接口的所有方法都是public方法,接口中抽象方法,可以不用abstract修饰(void 实际上就是abstract)
- 一个普通类的实现接口必须将该接口里面的所有方法都实现
- 抽象类实现接口,可以不用实现接口的方法
- 一个类可以实现多个接口(解决了类的单继承问题)
- 接口中的属性只能是final,而且是pubilic static final修饰符,比如int a=1;实际上是public static final int a=1;必须初始化
- 接口中的属性的访问形式:接口名.属性名
- 接口不能继承其他类
- 接口修饰符只能是public和默认,这点和类的修饰符是一样的。
类和接口,抽象类的对比
- 类和抽象类的对比:其实抽象类就多了个抽象方法,本质还是类,拥有类里面拥有的东西
- 抽象方法和接口的对比:抽象方法的权限不能是private,也不能被static和final修饰,接口的抽象方法更加抽象,权限只能是public,也不能被static和fianl修饰,接口中的属性都是public static final 修饰,接口中不能有代码块。
- 当子类继承了父类,就自动的拥有了父类的功能,如果子类想要扩展功能,就可以实现接口的方式扩展
- 继承的价值:解决了代码的复用性和可维护性
- 接口的价值:设计设计好各种的规范(方法),让其他类去实现这些方法,更加灵活。