脚本宝典收集整理的这篇文章主要介绍了12、面向对象(高级),脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
独立于对象之外的变量和方法
(1)为什么需要静态变量?
在实际开发场景中,处理问题时,会需要两个类在同一内存区域中共享一个数据,或共用一个方法,此时就需要使用到静态变量和静态方法
(2)什么是静态变量?
类变量也叫静态变量,静态属性,为该类所有对象共享的变量
(3)怎么使用静态变量?
类名.类变量名;(推荐)
对象名.类变量名;
(4)使用静态变量时需要注意的问题
(1)什么是静态方法?
访问修饰符 static 数据返回类型 方法名() {}
(推荐)static 访问修饰符 数据返回类型 方法名() {}
(2)怎么使用静态方法?
在满足访问修饰符的前提下
类名.类方法名
对象.类方法名
(3)使用静态方法时需要注意的问题
this
,suPEr
)public static void main(String[] args) {}
(1)理解main方法
public
static
String[] args
的意义:传递参数——在控制台输入:java 文件名 参数一 参数一 ...
(2)说明
{}
(1)代码块
代码块属于类中的成员(类的一部分)
类似于方法,将逻辑语句封装在方法体中,通过{}
包围起来
但是与方法不同,代码块没有方法名,没有返回,没有参数,只有方法体,而且不用通过对象或类显式调用,而是加载类,或创建对象时隐式调用
(2)语法
修饰符 {
代码;
};
;
可以省略(3)三种代码块
(1)静态代码块随着类的加载而执行,且只执行一次
(2)类什么时候被加载
(3)构造代码块在创建实例时被隐式地调用,创建一次,调用一次
(4)代码块在创建一个对象时,在一个类中的调用顺序是
(5)构造器前隐含了super()
构造器,和调用构造代码块,即父类构造器优先于调用本类构造代码块
(6)创建一个子类对象时,他们的静态代码块,静态属性初始化,构造代码块,普通属性初始化,构造方法的调用顺序如下:
(7)静态代码块只能直接调用静态成员,构造代码块可以调用任意成员
(1)构造器的补充机制,相当于另外一种形式的构造器,可以做初始化的操作
(2)如果多个构造器中都有重复语句,可以抽取到代码块中,提高代码的重用性
(1)什么是设计模式?
设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格以及解决问题的思考方式
(2)什么是单例模式? 所谓的单例模式,即单个实例,指采取一定的方法保证在整个的软件系统中只能存在一个实例,并且该类只提供一个取得其对象的方法
(3)饿汉式
getInstance()
public class SingleTon01 {
//通过类调用静态方法获取对象
GirlFriend instance = GirlFriend.getInstance();
}
class GirlFriend {
PRivate String name;
//2、在类的内部创建对象
//为了能在静态方法中使用,需要将其修饰为静态方法
private static GirlFriend gf = new GirlFriend("小花花");
//保证只有一个实例对象
//1、构造器私有化
private GirlFriend(String name) {
this.name = name;
}
//3、提供暴露的静态公共方法,返回gf对象
public static GirlFriend getInstance() {
return gf;
}
}
(4)懒汉式
public class SingleTon02 {
}
class Cat {
private String name;
//不直接实例化
private static Cat cat;
private Cat(String name) {
this.name = name;
}
//懒汉式——在静态的公共方法中进行对象的实例化
public static Cat getInstance() {
if (cat == null) {//保证单例
cat = new Cat("小可爱");
}
return cat;
}
}
(5)比较
可以用来修饰类,属性,方法和局部变量
(1)当不希望类被继承时,用final修饰——修饰类
(2)当不希望父类的某个方法被子类重写时,用final——修饰方法
(3)当不希望类的某个属性被修改时,用final——修饰属性
(4)不希望某个局部变量被修改——修饰局部变量
(1)final修饰的属性又叫做常量,一般用XX_XX_XX来命名
(2)final修i是的属性在定义时,必须赋初始值,且不能修改
赋值的位置
public final double TAX_RATE = 0.08;
类的成员变量,局部变量在使用前初始化即可
(3)如果final修饰的属性为静态的,则初始化位置只能在如下所示位置
位置
类加载——》静态代码块执行
(4)final修饰类不能继承,但可以实例化对象
(5)如果不是final类,含有final方法,则该方法不能重写,但可以被继承
(6)final类中所有的方法被隐式设置为final方法
(7)final不能修饰构造方法
(8)final和static往往搭配使用,效率更高,不会导致类加载(底层做了优化)
(9)包装类(Integer,Double,Float,Boolean)都是final类,String也是final类
父类方法的不确定性
当父类的某些方法需要声明,但又不确定该如何实现时,可以将其声明为抽象方法,那么这个类就是抽象类
抽象类除了继承毫无意义
(1)用abstract关键字来修饰一个类时,类为抽象类
语法:访问修饰符 abstract class 类名 {}
(2)抽象方法
语法:访问修饰符 abstract 返回类型 方法名(形参列表);
(无方法体)
(3)抽象类的价值在于设计,是设计者设计好后,让子类实现抽象类
(4)抽象类为考官常考知识点,子啊框架和设计模式中涉及较多
(1)抽象类不能实例化
(2)抽象类不一定要有抽象方法,而且可以有实现方法
(3)有抽象方法一定是抽象类
(4)abstract只能修饰类和方法
(5)抽象类仍然是类,可以有任意类可以有的成员
(6)抽象方法不能有方法体
(7)如果一个类继承了抽象类,则必须实现(重写)抽象类的所有抽象方法,除非它也声明为abstract类
(8)抽象方法不能使用private,final和static来修饰,因为与重写向违背
抽象类体现的就是一种模板模式的设计,抽象类作为子类的通用模板
子类在抽象类的基础上进行扩展、改造,但子类总体上会保留抽象类的行为
(1)当内部功能一部分实现是确定的,一部分实现是不确定的,这时可以把不确定的部分暴露出去,由子类实现
(2)编写一个抽象父类,父类提供了多个子类的通用方法,并把一个或多个方法留给其子类实现,就是一种模板模式
public class AbstractExercise01 {
public static void main(String[] args) {
//创建员工和经理
CommonEmployee commonEmployee = new CommonEmployee("jack", 51, 2000);
Manager manager = new Manager("tony", 52, 20000, 100000);
commonEmployee.work();
manager.work();
}
}
//抽象类
abstract class Employee {
private String name;
private int id;
private double salary;
public Employee(String name, int id, double salary) {
this.name = name;
this.id = id;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public abstract void work();
}
class Manager extends Employee {
private double bonus;//奖金
public Manager(String name, int id, double salary, double bonus) {
super(name, id, salary);
this.bonus = bonus;
}
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
@override
public void work() {
System.out.println("经理" + this.getName() + "正在工作中...");
}
}
class CommonEmployee extends Employee {
public CommonEmployee(String name, int id, double salary) {
super(name, id, salary);
}
@Override
public void work() {
System.out.println("员工" + this.getName() + "正在工作中...");
}
}
接口就是一个标准
(1)接口被用来描述一种抽象(用来实现多继承)
(2)接口被用来实现抽象,抽象类也被用来实现抽象,为什么一定要用接口,二者之间的区别是什么?
(3)为不同类顺利交互提供标准
接口就是给出一些没有实现的方法,封装到一起,在某个类要使用的时候,根据具体情况,实现方法
//定义接口
interface 接口名 {
//属性
//方法
}
//实现
class 类名 implements 接口名 {
//属性
//方法
//必须实现的接口的抽象方法
}
指定标准,接口是需求的实际体现
(1)接口不能被实例化
(2)接口中的所有方法是public方法,接口中抽象方法可以不用abstract修饰,因为interface中方法默认为public abstract修饰
(3)一个普通类实现接口,就必须将该接口的所有方法都实现
(4)除非声明为抽象类,上(3)可不用全部实现
(5)一个类可以实现多个接口
(6)接口中的属性 ,只能是final
,而且是public static final
修饰
(7)接口属性的访问:接口名.属性;
(8)接口不能继承类,但可以继承多个别的接口
(9)接口修饰符和类一样,只能是public和默认的
(1)解决问题不同
(2)接口比继承更灵活
is-a
关系,子类是一个父类like-a
,类像一个接口(3)接口在一定程度上实现代码解耦
接口规范性+动态绑定
(1)参数的多态性
接口引用可以指向实现了接口的类的对象
(2)多态数组
public class Arr {
public static void main(String[] args) {
//多态数组
usb[] usbs = new Usb[2];
usbs[0] = new Phone();
usbs[1] = new Camera();
//调用
for(int i = 0; i < usbs.length; i++) {
usbs[i].work;//动态绑定
if (usbs[i] instenceof Phone) {
((Phone)usbs[i]).call();//向下转换:前提是引用指向的对象本来就是Phone类
}
}
}
}
//接口
interface Usb {
void work();
}
class Phone implements Usb {
public void call() {
"手机打电话".sout;//输出
}
//实现
public void work() {
"手机工作中".sout;
}
}
class Camera implements Usb {
public void work() {
"相机工作中".sout;
}
}
(3)接口的多态传递
interface IH{}
//IG 继承 IH
interface IG extends IH {}
//Teacher类实现IG接口的同时也实现了IH接口
class Teacher implements IG {}
//主方法简写
main {
IG ig = new Teacher();//一个IG接口的引用指向了一个Teacher类的实例
IH ih = new Teacher();//一个IH接口的引用指向了一个Teacher类的实例
}
每个内部类都能独立地实现一个接口,无论外部类是否实现了接口,对内部类而言都不影响,从而结局了Java多继承的问题
一个类的内部完整地嵌套了另一个类结构,被嵌套的类称为内部类,嵌套其他类的类为外部类,是类的第五大成员(属性,方法,构造器,代码块,内部类)
最大的特点:可以直接访问外部类的私有属性,并且可以体现类之间的层级关系
class 外部类 {
class 内部类 {
}
}
class 外部其他类 {
}
定义在外部类成员的位置上的内部类,按静态非静态划分为
成员内部类
静态内部类
定义在外部类成员的局部位置上的内部类,按有无类名区分为
外部类的成员位置,且非static
(1)可以直接访问外部类的所有成员,包含私有的
(2)地位为成员,则可以添加任意访问修饰符
(3)作用域:和外部其他类一样,整个类体
(4)成员内部类访问外部类:直接访问
(5)外部类访问成员内部类成员:在外部类里建立成员内部类对象,再调用
(6)外部其他类访问成员内部类成员
外部类.内部类 引用 = 外部类对象.new 内部类(实参列表);
(7)外部类和内部类成员重名时,就近原则,若要访问外部类——外部类名.this.成员;
外部类名.this
:表示指向外部类的对象
外部类的成员位置,为静态
(1)可以访问外部类所有静态成员,不能访问非静态成员
(2)可以添加任意修饰符
(3)作用域:整个类体
(4)静态内部类直接访问外部类成员
(5)外部类访问静态内部类成员:实例化静态内部类一个对象,再调用、
静态内部类只是说明该类属于外部类,而不属于外部类实例化的对象,而静态内部类的非静态成员,依然和静态内部类的对象相联系,所以需要实例化静态内部类对象后再调用目标成员
(6)外部其他类访问静态内部类
外部类.静态内部类 引用 = new 外部类.静态内部类();
引用.成员;
静态成员可以通过类名来调用,静态内部类为静态成员,ps:静态内部类的成员不一定为静态
(7)外部类和内部类成员重名时,就近原则,若要访问外部类——外部类名.this.成员;
通常在方法中,有类名
(1)可以直接访问外部类的所有成员,包含私有的
(2)地位为一个局部变量,不能使用权限修饰符,但可以使用final关键字
(3)作用域:仅在定义它的方法或代码块中
(4)局部内部类访问外部类成员:直接访问
(5)外部类访问局部内部类:满足作用域的条件下(即在方法中),创建对象再访问
(6)外部其他类无法访问局部内部类:因为局部内部类为一个成员变量
(7)外部类和内部类成员重名时,就近原则,若要访问外部类——外部类名.this.成员;
匿名的局部内部类,不是没名,而是系统自动分配类名
(1)语法
new 类或接口(参数列表) {
类体;
};
//底层运行逻辑
class 外部类名$02 implements 类或接口 {//实现了类接口或继承了类
类体;
}
new 外部类名$02();//实例化一个匿名内部类的对象
//例子
public class AnonymousInnerClass {//外部其他类
public static void main(String[] args) {
Outer outer = new Outer();
outer.method();
}
}
class Outer {//外部类
private int n1 = 10;//属性
public void method() {//外部类的方法中建立内部类
/**
* 1、需求:使用A接口,并创建对象
* 2、传统方式:创建一个类重写方法,实现接口,并创建对象
* 3、若tiger类只使用一次,后面不再使用
* 4、解决方案:使用匿名内部类,来简化开发
* */
//基于接口的匿名内部类
/**
* 匿名内部类基于接口的解析
* 1、tiger的编译类型为:IA接口类型
* 2、tiger的运行类型为:匿名内部类,匿名内部类并非没有名字,只是由系统分配类名,底层如下
* -iA() {类体};:创建了一个实现了接口的匿名内部类,注意为一个语句,需要分号“ ; ”
* class Outer$01 implements IA {
* 类体
* };
* new IA() {}; :创建了一个匿名内部类的对象
* new Outer$01();
* IA tiger = new IA() {};
* 将实例化的一个实现了A接口的匿名内部类的对象的地址传递给tiger
*3、匿名内部类使用一次,就不能再使用了,但是tiger可以重复使用
* */
IA tiger = new IA() {//基于接口的匿名内部类
@Override
public void cay() {
System.out.println("老虎嗷嗷叫");
}
};
//在外部类中,在内部类作用域即方法中,调用内部类的成员——创建一个指向内部类对象的引用,用对象来调用方法
tiger.cay();
// Tiger tiger = new Tiger();
// tiger.cay();
//基于类的匿名内部类
/**
* 匿名内部类基于类的解析
* 1、father的编译类型:Father
* 2、father的运行类型:Outer$2 father对象的运行类型:class com.zyhstu.innerclass.Outer$2
* -Father("jack") {类体};:创建了一个继承了Father父类的Outer$2子类
* class Outer$2 extends Father {
* 类体;
* };
* -new Father("jack") {类体};:创建一个匿名内部类Outer$2的对象,并将jack自动传给Father的构造器
* new Outer$2() {类体};
* -Father father = new Father("jack") {};
* 实例化一个继承了Father父类的Outer子类的对象,并将地址传递给一个Father的引用
* */
Father father = new Father("jack") {
@Override
public void test() {
System.out.println("匿名内部类重写了test()方法");
}
};
father.test();
System.out.println("father对象的运行类型:" + father.getClass());
//基于抽象类的匿名内部类
Animal animal = new Animal() {
@Override
void eat() {
System.out.println("小狗吃骨头");
}
};
animal.eat();
}
}
interface IA {
public void cay();
}
//class Tiger implements IA {
// @Override
// public void cay() {
// System.out.println("老虎嗷嗷叫");
// }
//}
//
//class Dog implements IA {
// @Override
// public void cay() {
// System.out.println("小狗汪汪叫");
// }
//}
class Father {//外部其他类
public Father(String name) {//构造器
}
public void test() {//方法
}
}
//抽象类
abstract class Animal {
abstract void eat();
}
(2)匿名内部类的使用
new 类或接口(实参列表) {
类体;
}.方法(方法实参);
类名 引用 = new 类或接口(实参列表) {
类体;
}
引用.方法(方法实参);
(3)注意事项
外部类名.this.成员;
以上是脚本宝典为你收集整理的12、面向对象(高级)全部内容,希望文章能够帮你解决12、面向对象(高级)所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。