1. 作用: 对Java对象进行初始化
2. 程序的执行顺序:
(1)声明成员变量的默认值;
(2)显式初始化、多个初始化块依次被执行(同级别下按先后顺序执行);
(3)构造器再对成员进行赋值操作。
3. 语法结构:
修饰符 class 类名{
{
语句;
}
}
4. 静态代码块
代码块只能被static修饰,被static修饰的代码块称为静态代码块,当类被载入时,类属性的声明和静态代码块先后顺序被执行,且 只执行一次。
static块用于给类初始化,随着类的加载而加载(初始化static属性或调用static方法)。
(1)例1:
class Person {
public static int total;
static {
total = 100;//为total赋初值
}
…… //其它属性或方法声明
}
(2)例2:
public class Person{
static int age;
static{ //只能使用静态属性和方法
age = 1;
showAge();
}
public static void showAge(){
System.out.println(this.age);
}
}
5. 注意
非静态代码块:没有static修饰的代码块
静态代码块:用static 修饰的代码块
6. 程序执行顺序
7. 代码块应用:
静态代码块通常用来初始化类属性,非静态代码块可用于初始化匿名内部类等。
例:匿名内部类
package practice1.test;
public class Person {
String name;
int age;
{
name = "XiaoMing";
age = 23;
}
public void showInfo() {
System.out.println("Person.showInfo");
}
public void showPersonInfo() {
System.out.println("Person.showPersonInfo");
}
}
package practice1.test;
public class Student extends Person{
String school;
@Override
public void showInfo() {
System.out.println("Student.showInfo");
}
public void showStudentInfo() {
System.out.println("Student.showStudentInfo");
}
public static void main(String[] args) {
/**
* stu继承父类,name和age默认为父类初始值,此时想要改变stu属性的值,
* 或想单独输出一些语句,或单独对某些方法重写,但不能影响其他对象实例化时的初始值,可以使用匿名内部类
*/
Student stu = new Student() {
{
super.age = 22;
super.name = "LiHua";
}
@Override
public void showInfo() {
System.out.println("匿名内部类重写的方法" + this.age + this.name);
}
};
stu.showInfo();
}
}
8. 给出下面程序的输出结果:
package test;
public class StaticDemo{
static {
System.out.println("b");
}
public static void main(String[] args) {
new StaticCode();
new StaticCode();
System.out.println("d");
}
static {
System.out.println("c");
}
}
class StaticCode{
static {
System.out.println("a");
}
}
/* 分析:
* 执行时先加载主类StaticDemo, 该类中的所有静态代码块随着类的加载也被加载,
* 因此按照代码块的顺序依次输出 b c, 之后new对象时加载StaticCode类, 输出 a,
* 最后输出 d。因此输出结果为: b c a d
*/
package test;
public class StaticDemo{
static {
System.out.println("e");
}
public static void main(String[] args) {
new StaticCode();
new StaticCode(4);
}
static {
System.out.println("c");
}
}
class StaticCode{
StaticCode() {
System.out.println("b");
}
static {
System.out.println("a");
}
{
System.out.println("c");
}
StaticCode(int x){
System.out.println("d");
}
public static void show() {
System.out.println("run");
}
}
//输出结果为: e c a c b c d
1.在Java中声明类、属性和方法时,可使用关键字final来修饰,表示“最终”。
2.举例
public final class Test{
public static int totalNumber = 5;
public final int ID;
public Test(){
//隐式赋值,可赋值多次
ID = ++totalNumber; //可在构造方法中给final变量赋值
}
public static void main(String[] args) {
Test t = new Test();
System.out.println(t.ID);
final int I = 10;
final int J;
J = 20;//显示赋值,只能赋值一次
// J = 30; //非法
}
}
随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类。
抽象类是用来模型化那些父类无法确定全部实现,而是由其子类提供具体实现的对象的类。
解决方案
Java允许类设计者指定:父类声明一个方法但不提供实现,该方法的实现由子类提供。这样的方法称为抽象方法。有一个或更多抽象方法的类称为抽象类。
Vehicle是一个抽象类,有两个抽象方法。
public abstract class Vehicle{
public abstract double calcFuelEfficiency(); //计算燃料效率的抽象方法
public abstract double calcTripDistance(); //计算行驶距离的抽象方法
}
public class Truck extends Vehicle{
public double calcFuelEfficiency( ) { //写出计算卡车的燃料效率的具体方法 }
public double calcTripDistance( ) { //写出计算卡车行驶距离的具体方法 }
}
public class RiverBarge extends Vehicle{
public double calcFuelEfficiency( ) { //写出计算驳船的燃料效率的具体方法 }
public double calcTripDistance( ) { //写出计算驳船行驶距离的具体方法}
注意:抽象类不能实例化,new Vihicle()是非法的。
编写一个Employee类,声明为抽象类,包含如下三个属性:name,id,salary。提供必要的构造器和抽象方法:work()。对于Manager类来说,他也是员工,还具有奖金(bonus)的属性。请使用继承的思想,设计CommonEmployee类和Manager类,要求类中提供必要的方法进行属性访问。
package practice1.test;
public abstract class Employee {
static int start_id = 1;
String name;
final int ID;
double salary;
public Employee(String name, double salary) {
this.name = name;
this.ID = start_id++;
this.salary = salary;
}
public abstract void work();
}
package practice1.test;
public class CommonEmployee extends Employee{
public CommonEmployee(String name, double salary) {
super(name, salary);
}
@Override
public void work() {
System.out.println("普通员工的工作");
}
public void getInfo() {
System.out.println("普通员工 " + "编号:" + this.ID + " 姓名:" + this.name + " 薪水:" + this.salary);
}
}
package practice1.test;
public class Manager extends Employee{
double bonus;
public Manager(String name, double salary, double bouns) {
super(name, salary);
this.bonus = bouns;
}
@Override
public void work() {
System.out.println("管理人员的工作");
}
public void getInfo() {
System.out.println("管理人员 " + "编号:" + this.ID + " 姓名:" + super.name + " 薪水:" + this.salary + " 奖金:" + this.bonus);
}
}
package practice1.test;
public class Test1 {
public static void main(String[] args) {
CommonEmployee com = new CommonEmployee("小明", 3000);
Manager man = new Manager("李华", 5000, 2000);
com.work();
com.getInfo();
man.work();
man.getInfo();
}
}
package test;
public class TestGetTime {
public static void main(String[] args) {
GetRunningTime grt = new GetTime();
double time = grt.getTime();
System.out.println(time);
}
}
/**
* 获取程序运行时间的工具类
* @author 14251
*
*/
abstract class GetRunningTime{
public final double getTime() {//不允许子类重写
double t1 = System.currentTimeMillis();
runningCode();
double t2 = System.currentTimeMillis();
return t2 - t1;
}
public abstract void runningCode();
}
class GetTime extends GetRunningTime{
@Override
public void runningCode() {
for(int i=0; i<3000; i++) {
if(i != 2999) {
System.out.print(i + ", ");
}else{
System.out.println(i);
}
if(i % 20 == 19) {
System.out.println();
}
}
}
}
class SubClass implements InterfaceA{ }
一个类可以实现多个接口,接口也可以继承其它接口。
用interface来定义。
所有成员变量都默认是由 public static final 修饰的。
所有方法都默认是由 public abstract 修饰的。
接口没有构造器。
接口采用多层继承机制。
子类只可以继承一个父类,但可以实现多个接口,多个接口用 “ , ” 分隔。
public class Student extends Person implements Interface1, Interface2{
@Override
public void test1(){
}
@Override
public void test2(){
}
}
interface Runner{
public void run();
}
interface Swimmer{
public double swim();
}
class Creator{
public int eat(){}
}
class Man extends Creator implements Runner, Swimmer{
public void run(){}
public double swim(){}
public int eat(){}
}
public class Test{
public static void main(String args[]){
Test t = new Test();
Man m = new Man();
t.m1(m);
t.m2(m);
t.m3(m);
}
public String m1(Runner f){
f.run();
}
public void m2(Swimmer s){
s.swim();
}
public void m3(Creator a){
a.eat();
}
}
interface MyInterface{
String s=“MyInterface”;
public void absM1();
}
interface SubInterface extends MyInterface{
public void absM2();
}
public class SubAdapter implements SubInterface{
public void absM1(){
System.out.println(“absM1”);
}
public void absM2(){
System.out.println(“absM2”);
}
}
实现类SubAdapter必须给出接口SubInterface以及父接口MyInterface中所有方法的实现。
模拟电脑主板工作方式:
package test;
/**
* 分析: 主板不知道未来会出现什么样的芯片插入到主板上, 因此只能预留出符合一定条件的插槽,
* 日后如果有新的芯片需要插到主板上, 只需要让该芯片满足主板预留插槽的条件即可。
*
* 程序中用PCI接口代表主板预留卡槽需要满足的条件, 因此传入到主板中的对象应为PCI接口的子类,
* 并且所有设备都要实现PCI接口。
*
* 思想: 有关联的几个功能之间(NetCard, SoundCard), 如果没有共同继承同一个接口(PCI),
* 那么在接收这几个功能的方法中(MainBoard)要添加许多语句, 尤其是添加新设备的功能时。
* 因此共同实现接口, 使用对象的多态性完成。
*
* 假设A、B有共同的功能a、b, 则将a、b抽取到接口I中, 让A、B实现接口I,
* 再创建一个类C, 在C内新建方法用于接收I的子类, 调用相应方法。
*
*
* @author 14251
*
*/
interface PCI{
public abstract void run();
public abstract void close();
}
class MainBoard{
public void mainBoardRun() {
System.out.println("MainBoard Run");
}
//若没有继承接口, 每新添加一个设备就要多两个方法
/*
public void runNetCard(NetCard n) {
if(n != null) {
n.run();
}else {
System.out.println("error");
}
}
public void closeNetCard(NetCard n) {
if(n != null) {
n.close();
}else {
System.out.println("error");
}
}
*/
public void runEquipments(PCI p) {
if(p != null) {
p.run();
}else {
System.out.println("error");
}
}
public void closeEquipments(PCI p) {
if(p != null) {
p.close();
}else {
System.out.println("error");
}
}
}
class NetCard implements PCI{
@Override
public void run() {
System.out.println("NetCard Run");
}
@Override
public void close() {
System.out.println("NetCard Close");
}
}
class SoundCard implements PCI{
@Override
public void run() {
System.out.println("SoundCard Run");
}
@Override
public void close() {
System.out.println("SoundCard Close");
}
}
public class Computer {
public static void main(String[] args) {
MainBoard mb = new MainBoard();
mb.mainBoardRun();
mb.runEquipments(new NetCard());
mb.runEquipments(new SoundCard());
mb.closeEquipments(new NetCard());
mb.closeEquipments(new SoundCard());
}
}
/*MainBoard Run
NetCard Run
SoundCard Run
NetCard Close
SoundCard Close*/
1. 概念:
FactoryMethod模式是设计模式中应用最为广泛的模式,在面向对象的编程中,对象的创建工作非常简单,对象的创建时机却很重要。FactoryMethod解决的就是这个问题,它通过面向对象的手法,将所要创建的具体对象的创建工作延迟到了子类,从而提供了一种扩展的策略,较好的解决了这种紧耦合的关系。
//接口BWM
package BWM;
public interface BWM {
void showInfo();
}
//接口BWMFactory
package BWM;
public interface BWMFactory {
BWM makeCar();
}
package BWM;
public class BWM3 implements BWM{
@Override
public void showInfo() {
System.out.println("This is BWM3");
}
}
package BWM;
public class BWM5 implements BWM{
@Override
public void showInfo() {
System.out.println("This is BWM5");
}
}
package BWM;
public class BWM7 implements BWM{
@Override
public void showInfo() {
System.out.println("This is BWM7");
}
}
package BWM;
public class BWM3Factory implements BWMFactory{
@Override
public BWM makeCar() {
System.out.println("BWM3 is maked");
return new BWM3();
}
}
package BWM;
public class BWM5Factory implements BWMFactory{
@Override
public BWM makeCar() {
System.out.println("BWM5 is maked");
return new BWM5();
}
}
package BWM;
public class BWM7Factory implements BWMFactory{
@Override
public BWM makeCar() {
System.out.println("BWM7 is maked");
return new BWM7();
}
}
package BWM;
public class MakeCar {
public static void main(String[] args) {
BWM bwm3 = new BWM3Factory().makeCar();
BWM bwm5 = new BWM5Factory().makeCar();
BWM bwm7 = new BWM7Factory().makeCar();
bwm3.showInfo();
bwm5.showInfo();
bwm7.showInfo();
}
}
package test;
//成员内部类
public class TestInnerClass {
public static void main(String[] args) {
OuterClass oc = new OuterClass();
oc.useInnerMethod();
//直接调用内部类方法
//OuterClass.InnerClass oi = new OuterClass().new InnerClass();
//oi.showInfo();
}
}
class OuterClass{
private int num = 4;
private int temp = 7;
class InnerClass{
int num = 5;
void showInfo() {
int num = 6;
System.out.println(temp);//内部类直接访问外部类成员, OuterClass.this.temp, 7
System.out.println(num);//6
System.out.println(OuterClass.this.num);//指定访问外部类的num, 4
System.out.println(this.num);//5
}
}
public void useInnerMethod() {
InnerClass in = new InnerClass();//外部类调用内部类成员时要实例化对象
in.showInfo();
}
}
package test;
//静态成员内部类
public class TestStaticInnerClass {
public static void main(String[] args) {
OuterClass.useInnerMethod();
}
}
class OuterClass{
static class InnerClass{
public void show() {
System.out.println("InnerClass Method");
}
private static void showInfo() {
System.out.println("InnerClass Static Method");
}
}
public static void useInnerMethod() {
new InnerClass().show();
InnerClass.showInfo();
}
}
内部类的使用场景:
package test;
public class TestLocalInnerClass {
public static void main(String[] args) {
new OuterClass().method(2);
/*
* Method Inner 1 2
* LocalClass
* ShowInfo
*/
new OuterClass().method(3);//形参声明为final, 为什么可以在传入2之后又传入3?
//因为传入2后,当方法执行完毕后,就释放内存,不存在二次赋值的情况,
//但不能在方法内部对传入的实参a进行再赋值。
}
}
class OuterClass{
private String name = "LocalInnerClass";
public void showInfo() {
System.out.println("ShowInfo");
}
public void method(int a) {
// a++;//错误, final常量不能二次赋值
//final int a, 自动添加。由于是局部变量, 调用结束后就释放,
//因此可以调用多次方法, 传入不同的实参, 而不会出现final常量只能赋值一次的情况
int x = 1;//final int x = 1; jdk1.8之后可以不写final, 编译器自动添加final
class Inner{
// private int num = 0;//可以有自己的成员属性
public void show(){
System.out.println("Method Inner " + x + " " + a);//只能访问final类型的局部变量
System.out.println(name);//局部内部类可以直接调用外部属性, 等价于下面写法
// System.out.println(OuterClass.this.name);
showInfo();//局部内部类可以直接调用外部方法
}
}
new Inner().show();
}
}
1. 基本用法:
package test;
interface Inter{
void show();
void showInfo();
}
abstract class Father{
public abstract void test();
}
public class TestAnonymousClass {
public static void main(String[] args) {
new AnonymousClass().method_1();
new AnonymousClass().method_2();
}
}
class AnonymousClass{
public void method_1(){
new Inter() {
public void show() {//实现接口或父类方法
System.out.println("show_1");
}
public void showInfo() {
System.out.println("showInfo_1");
}
public void ownMethod() {//可以实现自己特有的方法
System.out.println("ownMethod_1");
}
}.show();//.showIndo()或.ownMethod(), 直接调用方法
}
public void method_2() {
//能否一次调用两个方法?
Inter in = new Inter() {//多态, 建立对象
public void show() {
System.out.println("show_2");
}
public void showInfo() {
System.out.println("showInfo_2");
}
public void ownMethod() {
System.out.println("OwnMethod_2");
}
};
in.show();
in.showInfo();
// in.ownMethod();//父类Inter中没有ownMethod()方法, 编译失败
}
}
class AnonymousInnerClass{
public void method_3() {
int x = 1;//final int x = 1;
new Father() {
private String str = "匿名内部类的成员属性";
public void test() {
System.out.println("method_3" + str + x);
}
};
}
}
2. 补全代码:
package test.practice;
interface Inter{
void method();
}
class Anonymous{
//补足代码, 用匿名内部类完成
static Inter function() {
return new Inter() {
public void method() {
System.out.println("method");
}
};
}
}
public class AnonymousPractice {
public static void main(String[] args) {
Anonymous.function().method();//已知
}
}
3. 形参是父类或接口时,传入的可以是匿名内部类:
package test.practice;
interface Inner{
void method();
}
public class MethodAnonymousClass {
public static void main(String[] args) {
show(new Inner() {
public void method() {
System.out.println("Inner method run");
}
});//注意书写
}
public static void show(Inner in) {
in.method();
}
}
4. 使用匿名内部类直接调用所需方法,不需要再创建类的对象:
package test.practice;
public class ObjectAnonymousClass {
public static void main(String[] args) {
//使用匿名内部类直接调用所需方法, 不需要再创建类的对象
new Object() {//Object类是根父类
public void method() {//所需方法实现
System.out.println("Object method");
}
}.method();
//使用Object匿名内部类直接调用方法时, 要避免创建父类引用,
//因为父类中可能没有子类定义的方法, 造成编译失败。
// Object o = new Object() {
// public void method() {
// System.out.println("Object method");
// }
// };
// o.method();//Object类中没有method方法, 编译失败
}
}
有三个类,假设为A、B、C,B和C中分别有一个print函数用来打印信息,现在A想同时继承B和C,并重写B和C的print方法,编写程序。
方法1:B和C都构造成A的内部类
package abc;
public class ATest {
public static void main(String[] args) {
A a = new A();
a.testB();
a.testC();
}
}
class A{
public void testB() {
new InnerB().printB();
}
public void testC() {
new InnerC().printC();
}
class InnerB extends B{
@Override
public void printB() {
System.out.println("InnerB");
}
}
class InnerC extends C{
@Override
public void printC() {
System.out.println("InnerC");
}
}
}
class B{
public void printB() {
System.out.println("B");
}
}
class C{
public void printC() {
System.out.println("C");
}
}
方法2:B被A继承,C构造成A的内部类
package abc;
public class ATest {
public static void main(String[] args) {
A a = new A();
a.printB();
a.testC();
}
}
class A extends B{
@Override
public void printB() {//调用内部类InnerB
System.out.println("InnerB");
}
public void testC() {//调用内部类InnerC
new InnerC().printC();
}
class InnerC extends C{
@Override
public void printC() {
System.out.println("InnerC");
}
}
}
class B{
public void printB() {
System.out.println("B");
}
}
class C{
public void printC() {
System.out.println("C");
}
}