Java面向对象(三)
一、static关键字的使用
1、static:静态的
2、static可以用来修饰属性、方法、代码块、内部类。
3、使用static修饰属性:静态变量(类变量)。
3.1、属性按是否使用static修饰,又分为:静态属性和非静态属性(实例变量)。
实例变量:当我们创建了类的多个对象,每个对象都独立的拥有一套类中的静态属性。当修改其中一个对象中的非静态属性时,不会导致其他对象中的同一属性发生改变。
静态变量:我们创建了类的多个对象,多个对象共享同一个静态变量。通过某一个类修改静态变量之后,通过其他对象调用此变量,变量的值是前一对象修改过后的值。
3.2、static修饰属性的其他说明
3.2.1、静态变量随着类的加载而加载。可以通过“类.静态变量”的方式进行调用。
3.2.2、静态变量的加载要早于对象的创建。
3.2.3、由于类只加载一次,则静态变量在内存中也只会存在一份,存在方法区的静态域中。
3.3、 静态属性 非静态属性
类 ✔ ✖
对象 ✔ ✔
3.4、类变量和实例变量内存分析

4、静态方法:使用static修饰的方法称为静态方法
4.1、随着类的加载而加载,可以通过“类.静态方法”的方式进行调用。
4.2、 静态方法 非静态方法
类 ✔ ✖
对象 ✔ ✔
4.3、静态方法中只能调用静态的方法或属性。
非静态方法中既可以调用非静态的方法和属性,也可以调用静态的方法和属性。
5、static注意点
5.1、在静态方法内不能用this关键字和super关键字
5.2、关于静态属性和静态方法的使用,可以从生命周期的角度去理解。
6、开发中,如何确定一个属性是否要声明为static?
>如果属性是可以被多个对象所共享的,不会随着对象的不同而不同,则可定义为静态属性。
开发中,如何确定一个方法是否要声明为static?
>操作静态属性的方法通常定义为静态方法。
>工具类中的方法通常定义为静态方法。
public class StaticTest {
public static void main(String[] args) {
Chinese.nation = "中国";
Chinese c1 = new Chinese();
c1.name = "姚明";
c1.age = 40;
c1.nation = "china";
Chinese c2 = new Chinese();
c2.name = "马龙";
c2.age = 30;
System.out.println(c1.nation);// 输出结果:china
c2.nation = "CHINA";
System.out.println(c1.nation);// 输出结果:CHINA
//对象可以调用静态方法
c2.show();
}
}
class Chinese {
String name;
int age;
static String nation;
public void eat() {
System.out.println("中国人吃中餐");
}
public static void show() {
System.out.println("我爱我的祖国");
// 不能调用非静态结构
// eat(); //Cannot make a static reference to the non-static method eat() from the type Chinese
// 可以调用静态结构
System.out.println(Chinese.nation);
walk();
}
public void info() {
System.out.println("name :" + name + ",age :" + age);
}
public static void walk() {
System.out.println("删库跑路");
}
}
二、单例设计模式
1、单例设计模式,就是采用一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例。
2、实现方式:
2.1、“饿汉式”
public class SingletonTest1 {
public static void main(String[] args) {
Bank bank1 = Bank.getInstance();
Bank bank2 = Bank.getInstance();
System.out.println(bank1 == bank2);//true
}
}
//饿汉式
class Bank {
// 1、私有化构造器
private Bank() {
}
// 2、内部创建类的对象
// 要求此对象必须声明为静态的
private static Bank instance = new Bank();
// 3、提供获取实例的方法
public static Bank getInstance() {
return instance;
}
}
2.2、“懒汉式”
public class SingletonTest2 {
public static void main(String[] args) {
Order order1 = Order.getInstance();
Order order2 = Order.getInstance();
System.out.println(order1 == order2);// true
}
}
//懒汉式
class Order {
//1、私有化构造器
private Order() {
}
//2、声明当前类的对象
private static Order instance = null;
//3、声明静态返回实例的方法。
public static synchronized Order getInstance() {
if (instance == null) {
instance = new Order();
}
return instance;
}
}
3、区分饿汉式和懒汉式
饿汉式:
坏处:对象加载时间长
好处:线程安全
懒汉式:
好处:延迟对象的加载,节省内存空间
4、应用场景:网站计数器、应用程序的日志系统、数据库连接池、读取配置文件、
三、类的成员之四:代码块(初始化块)
1、代码块的作用:用于初始化类、对象。
2、代码块如果有修饰符的话,只能使用static。
3、分类:静态代码块、非静态代码块
4、静态代码块:
4.1、内部可以有输出语句。
4.2、随着类的加载而执行。
4.3、作用:初始化类的信息。
4.4、如果一个类中定义了多个静态代码块,则按其声明的先后顺序执行。
4.5、静态代码块的执行,要先于非静态代码块。
4.6、静态代码块内只能调用静态的属性、静态的方法、不能调用非静态结构。
5、非静态代码块:
5.1、内部可以有输出语句。
5.2、随着对象的创建而执行。
5.3、每创建一个对象执行一次。
5.4、作用:可以在创建对象时,对对象的属性等进行初始化。
5.5、如果一个类中定义了多个非静态发代码块,在对象创建时按其声明的先后顺序执行。
5.6、非静态代码块内可以调用静态属性,静态方法,非静态属性,非静态方法。
public class BlockTest {
public static void main(String[] args) {
String desc = Persion.desc;
Persion p1 = new Persion();
}
}
class Persion {
// 属性
String name;
int age;
static String desc = "我是人类";
// 构造器
public Persion() {
}
public Persion(String name, int age) {
this.name = name;
this.age = age;
}
// 非静态代码块
{
System.out.println("block-2");
}
{
System.out.println("block-1");
}
// 静态代码块
static {
System.out.println("static block-2");
}
static {
System.out.println("static block-1");
}
// 方法
public void eat() {
System.out.println("吃饭");
}
@Override
public String toString() {
return "Persion [name = " + name + ",age = " + age + "]";
}
public static void info() {
System.out.println("我是一个快乐的人!");
}
}
四、属性赋值的先后顺序
1、默认初始化(数据类型默认值)。
2、显式初始化 / 在代码块中赋值。(按先后顺序)
3、构造器中初始化。
4、有了对象之后,通过“对象.属性”或“对象.方法”的方式,进行赋值。
五、final关键字
1、final可以修饰的结构:类、方法、变量。
2、final修饰的类不能被其他类继承。
3、final修饰的方法不能被重写。
4、final修饰的变量为常量。(常量名称通常用大写字母表示)
4.1、final修饰属性:可以赋值的位置有:显式初始化、代码块中初始化、构造器中初始化。
4.2、final修饰局部变量:
final修饰形参时,表明此形参是个常量。当我们调用此方法时,给常量形参赋一个实参,一旦赋值以后,就只能在方法体内使用此形参,但不能重新赋值。
5、static final 用来修饰属性:全局常量。
六、抽象类与抽象方法(abstract关键字使用)
1、abstract:抽象的。
2、abstract可以用来修饰的结构:类、方法。
3、abstract修饰类:抽象类
3.1、abstract修饰的类不能实例化。
3.2、抽象类中一定有构造器,便于子类对象实例化时调用。
3.3、开发中,都会提供抽象类的子类,让子类对象实例化,完成相关操作。
4、abstract修饰方法:抽象方法。
4.1、抽象方法只有方法的声明,没有方法体。例:public abstract void setXxx();
4.2、包含抽象方法 的类一定是抽象类。但抽象类中可能没有抽象方法。
4.3、若子类重写了父类中的所有的抽象方法后,方可实例化。
若子类没有重写父类中的所有的抽象方法,则此子类也是一个抽象类,需要用abstract修饰。
5、abstract使用时注意点:
5.1、abstract不能修饰属性,构造器等结构。
5.2、abstract不能修饰私有方法、静态方法、final修饰的方法、final修饰的类。
public class AbstractTest {
}
abstract class Persion {
String name;
int age;
public Persion() {
}
public Persion(String name, int age) {
this.name = name;
this.age = age;
}
/*
* public void eat() { System.out.println("人吃饭"); }
*/
public void walk() {
System.out.println("人走路");
}
public abstract void eat();
public abstract void breath();
}
class Student extends Persion {
public Student(String name, int age) {
super(name, age);
}
@Override
public void eat() {
// TODO Auto-generated method stub
}
@Override
public void breath() {
// TODO Auto-generated method stub
}
}
七、抽象类的匿名子类
public class PersionTest {
public static void main(String[] args) {
method(new Student());
Worker w1 = new Worker();
method1(w1);// 非匿名类 非匿名对象
method1(new Worker());// 非匿名类 匿名对象
Persion p = new Persion() {// 创建了匿名子类对象P
@Override
public void eat() {
// TODO Auto-generated method stub
}
@Override
public void breath() {
// TODO Auto-generated method stub
}
};
// 创建匿名子类的匿名对象
method1(new Persion() {
@Override
public void eat() {
// TODO Auto-generated method stub
}
@Override
public void breath() {
// TODO Auto-generated method stub
}
});
}
public static void method(Student s) {
}
public static void method1(Persion p) {
p.eat();
p.breath();
}
}
class Worker extends Persion {
@Override
public void eat() {
// TODO Auto-generated method stub
}
@Override
public void breath() {
// TODO Auto-generated method stub
}
}
八、接口:interface
1、 接口用interface来定义。
2、Java中接口和类是并列的两个结构。
3、如何定义接口:
3.1、JDK7及以前:只能定义全局常量和抽象方法。
3.1.1、全局常量:只能定义public static final的,可以省略不写。
3.1.2、抽象方法:只能定义为public abstract的,可以省略不写。
3.2、JDK8:除了定义全局变量和抽象方法外,还可以定义静态方法、默认方法(default修饰)。
3.2.1、接口中定义的静态方法,只能通过接口来调用。
3.2.2、通过实现类的对象可以调用接口中的默认方法。
如果实现类重写了接口中的默认方法,调用时,调用的是重写以后的方法。
3.2.3、如果子类(或实现类)继承的父类和实现的借口中声明了同名同参数的方法,那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数的方法。------>类优先原则。
3.2.4、如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法,那么实现类在没有重写此方法的情况下报错。------>接口冲突。这就需要我们必须在实现类中重写此方法。
3.2.5、在实现类中调用接口中被重写的方法: 接口名.super.method();
3.2.6、默认方法可以通过实现类对象来调用。
4、接口中不能定义构造器,即接口不能被实例化。
5、Java开发中,接口通过让类去实现(implements)的方式来使用。
如果实现类覆盖了接口中的所有抽象方法,则此实现类就可以实例化。
如果实现类没有覆盖接口中所有的抽象方法,则此实现类仍为一个抽象类。
6、Java类可以实现多个接口,弥补了 Java单继承的局限性。
格式:class AA extends BB implements CC , DD{}
7、接口与接口间可以继承,而且可以多继承。
九、类的成员之五:内部类
1、Java中允许将一个类A声明在类B中,则类A就是内部类,类B称为外部类。
2、内部类的分类:成员内部类、局部内部类(方法内,代码块内,构造器内)。
3、成员内部类:
3.1、作为外部类成员:
3.1.1、调用外部类的结构。例:“Persion.this.eat();”。
3.1.2、可被static修饰。
3.1.3、可以被4种不同权限修饰。
3.2、作为一个类:
3.2.1、类内可以定义属性、方法、构造器等。
3.2.2、可被final修饰,表示此类不能被继承;不使用final就可以被继承。
3.2.3、可以被abstract修饰。
4、使用
4.1、如何实例化成员内部类的对象。
4.2、如何在成员内部类中区分调用外部类的结构。
4.3、开发中局部内部类的使用。
5、注意点
在外部类方法中的局部内部类的方法,调用该内部类所在方法的局部变量时,要求此局部变量声明为final的。
JDK7及以前的版本该局部变量必须显式声明为final的。
JDK8及以后的版本可以省略final的声明。
public class InnerClassTest { public static void main(String[] args) { //创建Dog实例(静态成员内部类)。 Person.Dog dog = new Person.Dog(); //创建Bird实例(非静态成员内部类)。 /* * No enclosing instance of type Persion is accessible. Must qualify the * allocation with an enclosing instance of type Persion (e.g. x.new A() where x * is an instance of Persion). * Persion.Bird bird = new Persion.Bird(); */ Person p = new Person(); Person.Bird bird = p.new Bird(); bird.sing(); System.out.println("" + "" + "" + "" + ""); bird.test("鹦鹉"); } //开发中局部内部类使用 //一般不用此方法 public void method() { //局部内部类 class AA { } } //常见使用方式 //例:返回一个实现了Comparable接口的类的对象 //方式一 // public Comparable getComparable() { // //创建实现Comparable接口的类 // class MyComparable implements Comparable{ // // @Override // public int compareTo(Object o) { // // TODO Auto-generated method stub // return 0; // } // // } // return new MyComparable(); // // } //方式二 public Comparable getComparable() { return new Comparable() { @Override public int compareTo(Object o) { // TODO Auto-generated method stub return 0; } }; } } class Person{ String name = "小明"; int age; public void eat() { System.out.println("人吃饭···"); } //静态成员内部类 static class Dog{ String name = "大黄"; int age; public void show() { System.out.println("汪汪汪·····"); } } //非静态成员内部类 class Bird{ String name = "凤凰"; public Bird() { } public void sing(){ System.out.println("一只鸟"); Person.this.eat();//调用外部类非静态的属性。 } //在成员内部类中调用外部类的结构 public void test(String name) { System.out.println(name);//方法形参 System.out.println(Person.this.name);//外部类属性 System.out.println(this.name);//内部类属性 System.out.println(new Person.Dog().name);//调用并列静态内部类 } } public void method() { //局部内部类 class AA { } } { //局部内部类 class BB{ } } public Person(){ //局部内部类 class CC{ } } }

浙公网安备 33010602011771号