final关键字有最终的,不可修改的含义
final使用场合
final 用于声明属性,方法和类
1)属性:定义就必须直接赋值或者在构造方法中进行赋值,并且后期都不能修改。
2)方法:定义必须有实现代码,并且子类里不可被覆盖。
3)类:不能被定义为抽象类或是接口,不可被继承。
如果某个变量被final修饰,那么该变量就成为常量,不能被修改,一般语法:
语法:权限修饰符 final 数据类型 常量名 = 值;
常量在声明时必须初始化,声明之后不能对其进行二次赋值,其后任何试图对常量进行赋值的语句都将报错。
赋值两种方式:构造方法赋值和声明时等号赋值
final属性赋值
1)final与static一起使用,声明方式有2种
1.在声明时同时赋值:private static final int age=20;
2.在声明时不赋值,在静态代码块赋值
private static final int age;
static{
age=21;
}
2)final不与static一起使用,声明方式有2种:
1.在声明时同时赋值:private final int age=20;
2.在声明时不赋值,在初始化代码块或者构造方法赋值
private static final int age;
{
age=21;
}
或者:
public TestFinal() {
age=21;
}
总的原则:保证创建每一个对象的时候,final属性的值是确定的
对参数做final修饰
在方法参数前面加final关键字,为了防止数据在方法体中被修改。
public void m1(final int a){
a=3;
}
如果将某个成员方法修饰为final,则意味着该方法不能被子类覆盖,这就和抽象方法必须由子类实现的规定互相矛盾,因此,final和abstract不能同时修饰一个方法
final方法的一般声明格式是:
[访问权限] final 返回值类型 方法名(参数列表) {
……
}
例子:
public class Animal {
public final void eat(){
System.out.println("动物在吃饭");
}
}
public class Dog extends Animal {
@Override//Error:(3, 17) java: Dog中的eat()无法覆盖Animal中的eat()
被覆盖的方法为final
public void eat() {
System.out.println("狗在啃骨头");
}
}
如果将某个类修饰为final,则说明该类无法被继承,一般语法
[访问权限] final class 类名 {
成员列表
}
案例:
public final class Animal {
public void eat(){
System.out.println("动物在吃饭");
}
}
public class Dog extends Animal {//Error:(1, 26) java: 无法从最终Animal进行继承
@Override
public void eat() {
System.out.println("狗在啃骨头");
}
}
如果类的某个属性,不管创建多少个对象,属性的存储空间只有唯一的一个,那么这个属性就应该用static修饰,被static修饰的属性被称为静态属性,被static修饰的方法被称为静态方法。
static属性可以使用对象.属性名调用,也可以直接用类名.属性名调用。
被static修饰的成员变量被称为静态成员变量或者是静态属性
静态属性是类的所有对象共享的,即不管创建了多少个对象,静态属性在内存中只有一个
案例:
package T02静态;
public class Employee {
String name; //对象变量或者实例变量,有几个对象在内存就有几份
double salary;
static int count;//属于类的变量,为所有该类的对象共享,在内存中只有一份
public Employee() {
}
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
count++;
}
}
package T02静态;
public class TestEmployee {
public static void main(String[] args) {
//创建两个对象
Employee employee1 = new Employee("冯凯伦", 5000);
employee1.count=10;
Employee employee2 = new Employee("开赛尔", 8000);
System.out.println(employee1.name+"的工资是:"+employee1.salary+",count="+employee1.count);//count=11
System.out.println(employee2.name+"的工资是:"+employee2.salary+",count="+Employee.count);//count=11
}
}
被static修饰的方法称为静态方法,不与某个特定的对象关联
权限修饰符 static 返回值类型 方法名(){}
调用方式:
1)对象名.方法名(实参列表);
2)类名.方法名(实参列表);
public class TestEmployee {
public static void main(String[] args) {
//创建两个对象
Employee employee1 = new Employee("冯凯伦", 5000);
employee1.count=10;
Employee employee2 = new Employee("开赛尔", 8000);
// employee1.show();
Employee.show();
}
}
总结
本类的方法之间的调用
静态方法可以被任何方法(静态方法和非静态方法)直接调用;
非静态方法可以被非静态方法直接调用;
非静态方法不能被静态方法直接调用,需要创建对象,用对象名调用。
不用类方法之间的调用
调用静态方法,使用类名直接调用 ;
非静态方法不能直接调用,需要创建对象,用对象名调用。
static代码块
随着类的加载而加载,只执行一次
用于给类进行初始化
实例化代码块
实例化代码块给对象初始化,在构造方法前执行
static代码块和实例化代码块同时出现时优先级
静态代码块>实例化代码块>构造方法
案例:验证代码块的执行顺序
package T04static代码块;
public class A {
static {
System.out.println("static代码块");
}
{
System.out.println("实例化代码块");
}
public A() {
System.out.println("构造方法");
}
}
package T04static代码块;
public class TestCopyRecursive {
public static void main(String[] args) {
A a = new A();
}
}
JDK1.5中引入了“Static Import”机制,借助这一机制,可以用略掉所在的类或接口名的方式,来使用静态成员
使用方法:
1.导入方法:import static 包名.类名.静态方法名
2.调用方法:方法名(实参列表)
案例:
package T04static代码块;
import static java.lang.Math.abs;
public class B {
public static void main(String[] args) {
int abs = abs(-20);
System.out.println("abs = " + abs);
}
}
=================
什么时候使用抽象?当描述一个类的时候,如果一个类不应该有对象,那么该类就可以定义为抽象类,
如果不能确定功能方法如何定义,功能方法应该描述为抽象方法
抽象类的概念: 如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类
抽象类的定义语法: public abstract class 类名{类体}
抽象方法的定义语法:public abstract 返回值类型 方法名(形参列表);
抽象类不可以被实例化,也就是不可以用new创建对象 ,但有构造方法,主要用于实例化子类调用抽象类构造方法初始化成员变量。
用abstract修饰的类就是抽象类。抽象方法必须定义在抽象类中。但是抽象类中不一定有抽象方法。
方法只有声明没有实现时,该方法就是抽象方法,需要用abstract来修饰,抽象方法必须定义在抽象类中,该类也必须被abstract来修饰。
抽象类通过其子类实例化,而子类需要覆盖掉抽象类中所有的抽象方法后才可以创建对象,否则该子类也是抽象类。
抽象类可以有成员属性和非抽象的成员方法。
案例:
package T05抽象类;
public abstract class Shape {
int n;
public Shape() {
System.out.println("Shape.Shape()构造方法");
}
public Shape(int n) {
System.out.println("Shape.Shape(int n)构造方法");
this.n = n;
}
public abstract double area();
public double girth(){
return 0;
}
}
package T05抽象类;
public class Rect extends Shape {
public Rect() {
super();
System.out.println("Rect.Rect()构造方法");
}
public Rect(int n) {
super(n);
}
@Override
public double area() {
return 0;
}
}
package T05抽象类;
public class TestCopyRecursive {
public static void main(String[] args) {
Rect rect = new Rect(10);
}
}
抽象类可以没有抽象方法。
抽象类可以继承普通类与抽象类。
抽象类不能直接使用类名创建实例,但是有构造方法,构造方法是让子类进行初始化。
abstract与其他修饰符的关系:
final与abstract不能共存:
final:它的作用 修饰类代表不可以继承 修饰方法不可重写
abstract修饰类就是用来被继承的,修饰方法就是用来被重写的。
static static修饰的方法可以用类名调用,对于abstract修饰的方法没有具体的方法实现,所以不能直接调用,也就是说不可以与static共存。
private private修饰的只能在本类中使用,abstract方法是用来被子类进行重写的,有矛盾所有不能共存.
1)相同点
访抽象类和普通类都是用来描述事物的,都在内部定义了成员。
2)不同点
普通类有足够信息来描述事物,抽身象类描述事物的信息有可能不够充足
普通类不能定义抽象方法,只能定义普通方法,抽象类中可以定义抽象方法,同时也可以定义普通方法
普通类可以被实例化,抽象类不可以被实例化
java接口是一系列方法的声明,是一些抽象的集合,一个接口只有抽象方法没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
简单地说,接口就是特殊的抽象类,即所有方法都是抽象方法的抽象类就是Java中的接口(interface)
一句话:接口就是一堆抽象方法的集合
[修饰符] interface 接口名{
[public] [static] [final] 数据类型 变量名; //接口中的成员变量就是常量
[public] [abstract] 方法( );/“?b
}
接口中的成员修饰符是固定的:
public static final 修饰的变量变常量,该值不能改变,只能读
修饰符:可选,用于指定接口的访问权限,可选值为public。即使省略,也依然是public。
接口名:必选参数,用于指定接口的名称,接口名必须是合法的Java标识符。一般情况下,要求首字母大写
方法:接口中的方法只有定义而没有被实现。
package T08接口;
public interface A {
public static final double PI=3.14159265;
void m1();
}
[访问权限修饰符] class 类名 [extends 父类名] [implements 接口列表]{
必须重写接口中的方法( ){ }
}
实现一个接口
package T08接口;
public interface A {
public static final double PI=3.14159265;
void m1();
}
package T08接口;
public class AdeImpl implements A {
@Override
public void m1() {
System.out.println("AdeImpl.m1()方法");
}
}
package T08接口;
public class TestCopyRecursive {
public static void main(String[] args) {
AdeImpl ade = new AdeImpl();
ade.m1();
}
}
类与接口之间是实现关系,类实现接口。
接口不可以被实例化
实现了接口的实现类必须重写接口中所有抽象方法后,这个子类才可以被实例化,否则报错。
一个类可以实现多个接口,多个接口用逗号分隔,也可以不实现接口。
Java不支持多继承,Java将多继承机制进行改良变成了多实现
一个类在继承另一个类同时,还可以实现多个接口
接口的出现避免了单继承的局限性
package T08接口;
public class AbcdeImpl extends D implements A,B,C {
@Override
public void m1() {
System.out.println("AbcdeImpl.m1");
}
@Override
public void m2() {
System.out.println("AbcdeImpl.m2");
}
@Override
public void m3() {
System.out.println("AbcdeImpl.m3");
}
@Override
public void m4() {
System.out.println("AbcdeImpl.m4");
}
}
1.接口与接口之间是继承关系,而且可以多继承
2.语法:
[修饰符] interface 接口名 extends 接口名,接口名{接口中的方法( ){}}
3.接口的出现避免了单继承的局限性
在Java中接口是一个比抽象类更加抽象的概念,由于只声明行为,因此在接口中的方法均是抽象的,下表中罗列了接口和抽象类的差异:
抽象类体现继承关系,一个类只能单继承接口体现实现关系,一个类可以多实现
抽象类是继承is a关系(所属关系)在定义该体系的基本共性内容接口是实现是like a关系(不所属关系)在定义该体系额外功能
10、接口可实现多继承原因 接口继承与类继承对比:
Java类的继承是单一继承,Java接口的继承是多重继承接口可实现多继承原因分析:
不允许类多重继承的主要原因是,如果A同时继承B和C,而B和C同时有一个D方法,A无法确定该继承那一个
接口全都是抽象方法,不存在实现冲突,继承谁都可以,所以接口可继承多个接口
11、JDK8接口的默认方法
Java8之前,Java接口纯粹是契约的集合,是一种程序设计的表达方式。从数据抽象的角度看,能够在不定义class的同时又可以定义type,是程
序设计中强大而有用的机制。Java姜口就定这当纯竿日女H上PX日o人白象
Java8之前,接口不能升级。因为在接口中添加一个方法,会导致老版本接口的所有实现类的中断
Java8之后,lambda表达式作为核心出现,为了配合lambda表达式,JDK中Collection库需要添加新的方法,如forEach(), stream()等,于是引入了默认方法(defender methods,Virtual extension metthods)。
默认方法是库/框架设计者的后悔药。对于以前的遗留代码,大家都不知
道有这个新方法,既不会调用,也不会去实现,如同不存在;编写新代码的程序员可以将它视为保底的方法体。类型层次中任何符合override规则
的方法,优先于默认方法,因为遗留代码可能正好有同样的方法存在
默认方法理论上抹杀了Java接口与抽象类的本质区别-前者是行为契约的集合,后者是接口与实现的结合体。当然,语法上两者的差别和以前一样。这就需要我们来自觉维护两者的本质区别,把默认方法作为库、框架向前兼容的手段
12、面向接口编程
三层架构Ul展示层业务层数据层
使用三层架构编写图书商城
⑴)登录功能
(⑵)修改密码
大总结:
1.final 最终,不可变
1.类:不能别继承
2.方法:不能被重写
3.变量:常量
2.static 静态的 类的 共享的
1.类变量 对象共享
2.类方法,
3.抽象类:abstract
4.接口:interface