static关键字_
- static是一个关键字,表示静态的意思,可以用来修饰成员变量,成员方法,代码块
格式: 修饰符 static 数据类型 变量名;
- 被static修饰的成员变量叫做静态成员变量\类变量
- 被static修饰的成员变量会被该类的所有对象共享
- 如果该类的某个对象修改了静态成员变量的值,那么该类的所有对象使用的都是修改后的值
访问方式:
- 对象名.静态成员变量名
- 类名.静态成员变量名 (推荐)
示例:
class Text{
// 非静态成员变量
int a;
// 静态成员变量
static int b = 50;
}
public class Demo{
public static void main(String[] args) {
Text tx = new Text();
tx.a = 10;
tx.b = 20;
System.out.println(tx.a + "," + tx.b); // 输出 10,20
Text tx2 = new Text();
System.out.println(tx2.a + "," + tx2.b); // 输出 0,20
Text.b = 30;
System.out.println(Text.b); // 输出 30
}
}
被static修饰的成员变量叫做静态成员变量\类变量
被static修饰的成员变量会被该类的所有对象共享(相当于全局变量)
如果该类的某个对象修改了静态成员变量的值,那么该类的所有对象使用的都是修改后的值
修饰成员方法_
修饰符 static 返回值类型 方法名(形参列名){
方法体
}
- 被static修饰的成员方法叫做静态方法
访问方式
- 对象名.方法名(实参/无参);
- 类名.方法名(实参/无参); (推荐)
示例:
class Text2{
// 非静态成员方法
public void show(){
System.out.println("非静态方法 show...");
}
// 静态成员方法
static public void show2(){
System.out.println("静态方法 show2...");
}
}
public class Demo2{
public static void main(String[] args) {
Text2.show2(); // 输出 静态方法 show2...
// 用对象访问
Text2 tx = new Text2();
tx.show();
tx.show2();
}
}
- 注意事项
静态方法中不能出现this关键字
静态方法中只能直接访问静态成员变量和静态成员方法
静态方法中不能直接访问非静态成员变量和非静态成员方法
非静态方法中可以直接访问一切成员变量和成员方法
修饰代码块_
static {
// 静态代码块
}
- 静态代码块所在位置( 类中方法外(类的成员位置) )
- 随着类的加载而执行,并且只执行一次
- 类的加载: 第一次使用该类的时候,就会加载,并且只加载一次
- 如果程序中某段代码只需要执行一次,就可以把该段代码放入静态代码块中 ( 比如加载驱动,读取配置文件中的数据… )
接口_
- 接口是Java语言中的一种引用类型,主要是用来存储方法的
接口中的成员:
- 常量
- 抽象方法
- 默认方法和静态方法 (JDK 8)
- 私有方法(JDK 9及以上)
定义接口需要使用interface关键字
(编译后也会产生class文件)
接口没有构造方法
,也不能创建对象
,所以一般都是供类实现的(implements),类似继承
实现接口的类叫做实现类,实现类如果是普通类必须重写接口中所有的抽象方法,否则实现类是一个抽象类
示例:
// 定义了一个接口 A
public interface A{
// 定义一个静态常量 (public static final修饰,而这三个修饰符可以省略不写)
public static final int NUM = 20;
// 定义一个抽象方法 (public abstract修饰,而这两个修饰符可以省略不写)
public abstract void show();
// 定义一个默认方法 (public default修饰,public可以省略不写,default不可以省略)
public default void show2(){
// 方法体
}
// 定义一个静态方法 (public static修饰,public可以省略不写,static不可以省略)
public static void show(){
// 方法体
}
}
实现接口_
// 单实现
public class 实现类名 implements 接口名{}
// 多实现
public class 实现类名 implements 接口名1,接口名2,接口名3,...{}
// 先继承后实现
public class 实现类名 extends 父类名 implements 接口名1,接口名2,接口名3,...{}
示例:
interface A{}
interface B{}
interface C{}
class Fu{}
// 单实现
class Zi implements A{}
// 多实现
class Zi2 implements A,B,C{}
// 先继承后实现
class Zi3 extends Fu implements A,B,C{}
接口中成员的访问特点_
- 接口中常量: 主要供接口名直接访问,也可以被实现类继承
- 接口中抽象方法:就是供实现类重写的
- 接口中默认方法:可以供实现类对象直接调用,或者在实现类中重写
- 接口中静态方法:只供接口名直接访问,不可以被实现类继承
- 接口中私有方法:只能在接口内部方法中调用,不可以被实现类继承
示例:
interface A{
int NUM = 20;
void show();
default void show2(){
System.out.println("我是默认方法");
}
static void show3(){
System.out.println("我是静态方法");
}
private void show4(){
System.out.println("我是私有方法");
}
}
class Imp implements A{
@Override
public void show() {
System.out.println("重写接口A的show方法"); // 必须重写否则实现类为抽象类
@Override
public void show2() {
System.out.println("重写接口A的show2方法");
}
}
public class Text{
public static void main(String[] args) {
// 访问接口中的常量
A.NUM;
Imp.NUM;
// 访问接口中的抽象方法
Imp = ip = new Imp();
ip.show();
// 访问接口中的默认方法
ip.show2();
// 访问接口中的静态方法
A.show3();
}
}
多实现时的几种冲突情况_
- 公有静态常量的冲突 (多实现常量冲突: 多个接口中同名的常量不能被实现类继承)
- 公有抽象方法的冲突 (抽象方法冲突: 必须重写一次抽象方法)
- 公有默认方法的冲突 (默认方法的冲突: 必须重写一次默认方法)
接口和接口的关系_
- 接口和接口之间是继承关系
// 单继承
public interface A{}
public interface B extends A{}
// 多继承
public interface A{}
public interface B{}
public interface C extends A,B{}
// 多层继承
public interface A{}
public interface B extends A{}
public interface C extends B{}
接口继承接口的冲突情况_
- 公有静态常量的冲突 (常量冲突: 多个接口中同名的常量不会被子接口继承,不同名的会被继承)
- 公有抽象方法冲突 (抽象方法冲突: 多个父接口中有相同的抽象方法,子接口只会继承一个抽象方法)
- 公有默认方法的冲突 (默认方法冲突: 多个父接口中有相同的默认方法,子接口必须重写默认方法(default))
继承的同时又实现存在的问题_
- 父类和接口的公有静态常量的冲突 (常量冲突: 实现类不会继承有冲突的常量)
- 父类和接口的抽象方法冲突 (抽象方法冲突: 实现类必须重写一次有冲突的抽象方法)
- 父类和接口的公有默认方法的冲突 (默认方法的冲突:
优先访问父类的
)
多态_
- 实现多态的前提条件
继承或者实现
父类引用指向子类对象 : Fu f = New Zi();
方法的重写(没有重写方法多态是没有意义的)
实现多态_
继承时的多态:
abstract class Animal{
public abstract void eat();
}
class Dog extends Animal{
@Override
public void eat() {
System.out.println("狗吃骨头...");
}
}
class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼...");
}
}
public class Test {
public static void main(String[] args) {
// 继承实现多态的三个条件
// 1,继承
// 2,父类的引用指向子类的对象
// 3,方法的重写
// 父类的引用指向子类的对象
Animal an = new Dog();
an.eat(); // 输出 狗吃骨头...
an = new Cat();
an.eat(); // 输出 猫吃鱼...
}
}
实现时的多态:
interface A{
void show();
}
class Imp implements A{
@Override
public void show() {
System.out.println("实现类重写的show...");
}
}
class Imp2 implements A{
@Override
public void show2() {
System.out.println("实现类重写的show2...");
}
}
public class Test {
public static void main(String[] args) {
//实现多态的三个条件:
//1,实现
//2,接口的引用指向实现类的对象
//3,方法的重写
// 接口的引用指向实现类的对象
A a = new Imp();
a.show(); // 输出 实现类重写的show...
a = new Imp2();
a.show(); // 输出 实现类重写的show2...
}
}
多态r的几种表现形式_
- 普通父类多态
public class Fu{}
public class Zi extends Fu{}
public class Test{
public static void main(String[] args){
Fu f = new Zi();// 多态
}
}
- 抽象父类多态
public abstract class Fu{}
public class Zi extends Fu{}
public class Test{
public static void main(String[] args){
Fu f = new Zi();// 多态
}
}
- 父接口多态
public interface IA{}
public class Imp implements IA{}
public class Test{
public static void main(String[] args){
IA a = new Imp();// 多态
}
}
形参多态_
形参多态(常用)
参数的类型是父类类型,那么就可以接收该父类类型的对象以及该父类类型的所有子类对象
示例:
class Fu{
public void show(){
System.out.println("ff");
}
}
class Zi extends Fu{
public void show(){
System.out.println("Zi");
}
}
class Zii extends Fu{
public void show(){
System.out.println("Zii");
}
}
public class Text {
public static void main(String[] args) {
show(new Zi()); // 输出 Zi
show(new Zii()); // 输出 Zii
}
public static void show(Fu f){
f.show();
}
}
返回值多态(常用)
返回值类型为父类类型,那么就可以返回该父类类型的对象,或者该父类类型的子类对象
示例:
class Fu{
public void show(){
System.out.println("ff");
}
}
class Zi extends Fu{
public void show(){
System.out.println("Zi");
}
}
class Zii extends Fu{
public void show(){
System.out.println("Zii");
}
}
public class Text {
public static void main(String[] args) {
show("Zi").show(); // 输出 Zi
show("Zii").show(); // 输出 Zii
}
public static Fu show(String tyep){
if("Zi".equals(tyep)){
return new Zi();
}else if("Zii".equals(tyep)){
return new Zii();
}else{
return null;
}
}
}
引用类型转换_
- 向上转型:
父类类型 变量名 = new 子类名(实参);
- 向下转型:
子类类型 变量名 = (子类类型) 父类类型的变量;
为了避免转型异常一般会使用instanceof
关键字来进行判断
- 格式:
变量名 instanceof 数据类型
如果变量指向的对象的数据类型是属于后面的数据类型,就返回true,否则返回false
示例:
class Fu{}
class Zi extends Fu{
public void show(){
System.out.println("Zi");
}
public void zi(){
System.out.println("子类独有");
}
}
class Zii extends Fu{
public void show(){
System.out.println("Zii");
}
}
public class Text {
public static void main(String[] args) {
Fu f = new Zi();
// 使用if 判断
if(f instanceof Zi){
Zi z = (Zi)f;
z.zi(); // 输出 子类独有
}
boolean b = (f instanceof Zii);
System.out.println(b); // 输出 false
}
}
内部类_
- 定义在类的成员位置(类中方法外)的类就叫做成员内部类
class 外部类名{
class 内部类名{
}
}
- 成员访问特点
成员内部类中的成员变量和成员方法在其他类中访问,需要创建成员内部类对象
外部类名.内部类名 对象名 = new 外部类名().new 内部类名();
示例:
class On{
int num = 10;
class In{
int num = 20;
public void show(){
System.out.println("我是内部类");
}
}
}
public class Text {
public static void main(String[] args) {
On.In oi = new On().new In();
System.out.println("oi.num = " + oi.num);// 输出 oi.num = 20
oi.show();// 输出 我是内部类
}
}
- 注意事项:
在成员内部类中,可以直接访问外部类的一切成员,包括外部类的私有成员
在外部类中,需要直接访问内部类的成员,需要创建内部类对象来访问
匿名内部类_
- 本质其实就是一个类的子类对象
- 本质其实就是一个接口的实现类对象
new 类名(){
必须重写所有抽象方法
};
new 接口名(){
必须重写所有抽象方法
};
- 使用场景
如果想得到一个抽象类的子类对象,那么就可以直接给该类的匿名内部类
如果想得到一个接口的实现类对象,那么就可以直接给该接口的匿名内部类
示例:
abstract class On{
int num = 10;
public abstract void show();
}
public class Text {
public static void main(String[] args) {
On o = new On(){
@Override
public void show() {
System.out.println("匿名内部类");
}
};
System.out.println(o.num); // 输出 10
o.show();// 输出 匿名内部类
}
}
示例:
interface On{
int NUM = 10;
public abstract void show();
}
public class Text {
public static void main(String[] args) {
On o = new On(){
@Override
public void show() {
System.out.println("接口的内部类");
}
};
System.out.println(o.NUM); // 输出 10
o.show();// 输出 接口的内部类
}
}
引用类型的使用_
- 引用类型作为方法参数和返回值:
引用类型作为方法的参数传递的是地址值
引用类型作为方法的返回值返回的是地址值
示例:
class Fu{
String name = "张三";
int age = 33;
public void show(){
System.out.println("引用类型作为参数和反回值");
}
}
public class Text {
public static void main(String[] args) {
Fu f = new Fu();
f.show(); // 输出 引用类型作为参数和反回值
Fu f2 = show(f);
System.out.println(f2.name); // 输出 张三
}
public static Fu show(Fu f){
System.out.println(f.age); // 输出 33
return f;
}
}
引用类型作为成员变量_
示例:
class Demo1{
String name;
public void show(){
System.out.println("Demo1");
}
}
class Demo2{
String name;
Demo1 dm;
}
public class Text {
public static void main(String[] args) {
Demo2 dm2 = new Demo2();
dm2.dm = new Demo1();
dm2.dm.show();
dm2.name = "张三";
System.out.println(dm2.name);
}
}