Java(基础09)
14. static关键字详解
示例一:
package com.oop.demo10;
//static
public class Student {//... final class ...被final修饰之后“断子绝孙”了,不能被继承
private static int age;//静态的变量 多线程会用到!
private double score;//非静态的变量
public void run(){
go();//非静态方法可以直接访问静态方法
}
public static void go(){
}
public static void main(String[] args) {
Student s1 = new Student();
System.out.println(Student.age);
// System.out.println(Student.score);
//Non-static field 'score' cannot be referenced from a static context
System.out.println(s1.age);
System.out.println(s1.score);
s1.run();//静态方法只能访问静态方法。只能通过new一个对象来实现。由于类加载机制(顺序)的问题。
Student.go();
go();
}
}
示例二:
package com.oop.demo10;
public class Person {
{//2.和Person类new出来的对象同时产生,在构造方法之前,可以用来赋初始值
//代码块(匿名代码块)
System.out.println("匿名代码块");
}
static {//1.最先加载,且只执行一次
//静态代码块
System.out.println("静态代码块");
}
public Person() {//3.
System.out.println("构造方法");
}
public static void main(String[] args) {
Person person1 = new Person();
System.out.println("==========");
Person person2 = new Person();
}
}
示例三:
package com.oop.demo10;
//静态导入包
import static java.lang.Math.PI;
import static java.lang.Math.random;
public class Test {
public static void main(String[] args) {
System.out.println(Math.random());
System.out.println(random());//需要静态导入包
System.out.println(PI);//需要静态导入包
}
}
15. 抽象类
- abstract修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
- 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
- 抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。
- 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
- 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。
示例一:(抽象类↓)
package com.oop.demo11;
//abstract 抽象类:(本质是)类 extends:只能单继承,所以用的不是很多。 (但是接口可以实现多继承,用的很多)
public abstract class Action {
//约束,等待其他人来实现
//abstract,抽象方法,只有方法名字,没有方法的实现!
public abstract void doSomething();
}
(继承了抽象类的子类↓)
package com.oop.demo11;
//抽象类的所有方法,继承了它的子类,都必须要实现它的方法,除非它的子类也是抽象类。
public class A extends Action{
@Override
public void doSomething() {
}
}
(入口↓)
package com.oop;
import com.oop.demo11.Action;
public class Application_d11 {
public static void main(String[] args) {
// new Action();//'Action' is abstract; cannot be instantiated. (抽象类)不能被实例化。
}
}
- 抽象类无法通过new实例,只能靠子类去实现(继承)它:这是个约束!(需要遵守)
- 抽象类中可以写普通的方法,抽象类可以没有抽象方法。(抽象类的子类必须重写抽象方法,可以不重写普通方法)
- 抽象方法必须在抽象类中,有抽象方法的类一定是抽象类。
- 抽象的抽象:约束。
- 思考题? 抽象类既然不能new对象,那有没有构造器?
- 答:有。即使没有提供任何构造函数,编译器仍然会为抽象类添加默认的无参数的构造函数。
- 如果没有构造函数,抽象类的子类将无法编译,因为任何构造函数中的第一条语句,都是隐式调用super();
- 思考题? 抽象类存在的意义?
- 答:提高开发效率。
- 抽象是将共性抽离出来,产生抽象性概念非具体。
- 抽象类还是很有用的重构工具,因为它们使得我们可以很容易地将公共方法沿着继承层次结构向上移动。
16. 接口的定义与实现
- 普通类:只有具体实现
- 抽象类:具体实现和规范(抽象方法)都有!
- 接口:只有规范(抽象方法)!
- 自身无法写方法。是专业的约束。
- 约束和实现两者分离:面向接口编程。
- 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须能…”的思想。例如,如果你是鸟则必须能飞;如果你是鱼则必须能游泳;
- 接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。
- 面向对象的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论 设计模式(23种) 都只针对具备了抽象能力的语言(例如,c++、java、c#等),就是因为设计模式所研究的,实际上就是如何合理地去抽象。
PS:声明类的关键字是class,声明接口的关键字是interface.
示例一:(接口一↓)
package com.oop.demo12;
//定义接口的关键字:interface. 接口都需要有实现类。
public interface UserService {
//常量
public static final int AGE = 99;//完整版,一般不写public static final
//一般也不在接口中定义常量。
// public abstract void add(){}
// Interface abstract methods cannot have body.接口抽象方法不能有方法体
// public abstract void add();完整版,一般不写public abstract.
//接口中的所有定义的方法其实都是抽象的 public abstract
void add(String name);//增
void delete(String name);//删
void update(String name);//改
void query(String name);//查
}
(接口二↓)
package com.oop.demo12;
public interface TimeService {
void timer();
}
(实现类↓)
package com.oop.demo12;
import java.sql.Time;
// 抽象类:extends
// 类 可以实现接口:implements 接口
// 实现了接口中的类,必须要重写接口中的方法。
// Java本身只支持单继承,但利用了接口实现了多继承
public class UserServiceImpl implements UserService, TimeService {
//“UserServiceImpl”类必须声明为抽象或在“UserService”中实现抽象方法“add(String)”
@Override
public void add(String name) {
}
@Override
public void delete(String name) {
}
@Override
public void update(String name) {
}
@Override
public void query(String name) {
}
@Override
public void timer() {
}
}
- 接口的作用:
- 起到约束作用
- 实现类可以通过implements实现多个接口(实现多继承)
- 降低模块间的耦合度,提高程序可扩展性。
- 接口的注意点:
- 接口中的常量都是默认 public abstract 修饰的
- 接口中的方法都是默认 public static final 修饰的
- 接口不能被实例化,接口中没有构造方法(默认的也没有)
- 必须要重写接口中的方法
- 定义一些方法,让不同的人实现
(例如,10个人都通过1个接口完成这份工作,但是调用的方法也许各不相同)
17. N种内部类
- 内部类就是在一个类的内部再定义一个类,例如,A类中定义一个B类,那么B类相对于A类来说就是内部类(即,B类是A类的内部类),而A类相对于B类来说就是外部类了。
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
示例一:(成员内部类Inner↓)
package com.oop.demo13;
public class Outer {
private int id = 10;
public void out(){
System.out.println("这是外部类的方法");
}
public class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
//从内部类获得外部类的私有属性
public void getID(){
System.out.println(id);
}
}
}
(入口↓)
package com.oop;
import com.oop.demo13.Outer;
public class Application_d13 {
public static void main(String[] args) {
//实例化外部类
Outer outer = new Outer();
//通过已经实例化的外部类来实例化内部类
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getID();
}
}
示例二:(静态内部类↓)
package com.oop.demo14;
public class Outer {
private int id = 10;
public void out(){
System.out.println("这是外部类的方法");
}
public static class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
// //从内部类获得外部类的私有属性
// public void getID(){
// System.out.println(id);
// }//先加载静态内部类导致拿不到id,除非将id定义为静态变量。
}
}
另:
package com.oop.demo15;
public class Outer {
}
//一个Java类中可以有多个class类,但是只能有一个public class
class A{
public static void main(String[] args) {
}
}
示例三:(局部内部类↓)
package com.oop.demo16;
public class Outer {
//局部内部类
public void method(){
class Inner{
public void in(){
//内部类里可以写方法
}
}
}
}
示例四:(匿名内部类↓)
package com.oop.demo16;
public class Test {
public static void main(String[] args) {
// Apple apple = new Apple();//初始化类且包含名字apple
new Apple().eat();//初始化类且不包含名字,这就是匿名内部类。不用将实例保存到变量中。
UserSerice userSerice = new UserSerice(){
@Override
public void hello() {
}
};//匿名内部类
}
}
class Apple{
public void eat(){
System.out.println("1");
}
}
interface UserSerice{
void hello();
}