【Java基础】第二章(上) | OOP之封装性

目录

| 封装

类与static

权限修饰符

关键字final

内部类

泛型


| 封装

类与static

类的定义

[public] class 类名{
    public 类名(参数列表){
        //有参构造方法
    }
    
    public 类名(){
        //无参构造方法
    }
    
    //Getter 和 Setter 方法
    //toString 方法
    //hashCode 方法
​
}

匿名对象

new Scanner(System.in).nextInt();

static关键字

  • 被static修饰的【类成员变量、方法】,可以直接通过类名调用(即使通过对象调用,也会被编译为通过类名调用)

    • 不能通过 this 和 supper 关键字调用,因为static和实例无关,和类有关

    • 因为static方法独立于任何示例,所以不能被abstract修饰

    • 静态的方法中不能访问类的非静态变量!只能访问也被static修饰的变量

    • 静态方法中可以直接调用本类的其他静态方法

    • 类的所有对象共享同一份static数据

  • static【静态代码块】,在类初次被加载的时候会被执行一次

    • 静态代码块仅在类创建的对象被第一次使用的时候才会调用一次。(而对象构造方法会在对象每次被使用的时候都调用)

    • 静态代码块的执行顺序最高,执行顺序:静态高于非静态(内存中,先创建静态,后创建非静态)

    • 如果有多个static静态代码块,则会按照其顺序依次执行

    • 应用:多个对象使用一个相同的数据 /给对象按照创建地顺序进行编号;


权限修饰符

类的不同位置说明

 不同修饰符在类的不同位置的访问权限(X代表不能访问):

 类的权限修饰符的使用规则(X代表不能使用):

 


关键字final

final 修饰类

修饰符 final class 类名称(){
   //...
}
  • 抽象类不能用final修饰

  • 当前这个类,不能有任何的子类,进而所有的成员方法不能进行覆盖重写

final 修饰方法

修饰符 final 返回值类型 方法名(参数){
	//...  
}
  • 抽象方法不能用final修饰

  • 当前这个方法,不能被覆盖重写

final 修饰局部变量

final 数据类型 局部变量名 = 数值 ;
  • 局部变量包括方法的参数、方法内定义的变量

  • 局部变量不会进行默认赋值null或者0,因此可以直接赋值,也可以先定义再在之后赋值(如 int num; num=2;)

    由于是局部变量,因此无法通过构造方法 / getter 进行赋值

  • 只能进行唯一的一次赋值

  • 数值不可改变(基本类型值不可改变,引用类型内容可变 但是地址不可改变)

final 修饰成员变量

final 数据类型 成员变量名 = 数值 ;
  • 成员变量会进行默认赋值0或者null,所以必须一步完成赋值!(直接 / 构造方法赋值)

    不能分步赋值!(无法通过 setter() 进行赋值)

  • 只能进行唯一的一次赋值

  • 数值不可改变(基本类型值不可改变,引用类型内容可变 但是地址不可改变)

总结


内部类

内部类 VS 类作为成员变量类型

 外部类、成员内部类、局部内部类 的修饰符规则

 

 

 

下面介绍一下三大内部类:成员内部类、局部内部类、匿名内部类

成员内部类

  • 可以被 public default protected private 修饰

  • 内部类可以随意访问所在的类

  • 同名变量的处理遵循 this super 规则

  • 使用

public class MyClass{
	//间接访问内部类。过渡方法
	public void innerMethodVisitByOutClass(){
		InnerClass inner = new InnerClass();
		inner.innerMethod();  //通过这个方法间接调用内部类方法
	}
	
	//MyClass的内部类
	public class InnerClass{
		public void innerMethod(){
			//...
		}
	}
}


class Test{
    public void outMethod(){
        //使用方法1:直接创建内部类对象
        MyClass.InnerClass innerClass = new MyClass().new InnerClass();

        //使用方法2:间接调用(通过类中的方法,间接访问内部类)
        MyClass myClass = new myClass();
        myClass.innerMethodVisitByOutClass();
	}
}

局部内部类

  • 局部内部类不能被任何权限修饰符修饰

  • 和成员内部类不同的是:局部内部类无法直接创建其对象!因此只能间接调用

  • 局部内部类只能使用final修饰的变量

    原因:new出来的对象在堆内存中,而局部变量是跟着方法走的 在栈内存当中。方法运行结束之后,立刻出栈,局部变量立刻消失。但是new出来的对象仍然会在堆内存中持续存在,直到垃圾回收消失。此时对象仍然存在,因此如果不把常量换在常量池中(不用final修饰的话),那么此时对象要使用变量的话,就不知道用哪一个了!

  • 使用

public class MyClass {
    //方法。方法内的都是局部变量
    public void localityMethod() {
        class LocalityInnerClass{
            //.......
        }
        
        LocalityInnerClass localityInnerClass = new localityInnerClass();   //在局部内部类所在的方法内,创建局部内部类对象
        LocalityInnerClass;   //使用局部内部类的属性
    }
}

class Test{
    public void outMethod(){
        MyClass myclass = new MyClass();
        myclass.localityMethod();  //间接调用局部内部类
    }
}


匿名内部类

  • 匿名内部类一般是针对接口而言的。

  • 目的:省略了类创建实现类的步骤

  • 语法

    <span style="background-color:#f8f8f8"><span style="color:#000000">接口名称</span> <span style="color:#000000">对象名</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">接口名称</span> (  ) {   <span style="color:#aa5500">//覆盖重写所有抽象方法   };</span></span>
  • 上述语法并不是直接new了接口!本质上还是通过实现类这一中介创建的对象,只不过省略了这一步骤(接口是不能直接new的!)

  • 匿名内部类,只能创建唯一一次的对象。若想多次创建对象,要么直接编写一个实现类,要么只能多次进行匿名对象的创建

  • 匿名对象 和 匿名内部类 没有任何关系! 前者省略的是对象名字,后者是接口创建对象的时候省略了中间创建实现类的步骤

    当然,也可以写一段【匿名对象 + 匿名内部类】的代码,如下

new MyInterfaceObject(){
	@Override
	public void method(){
		System.out.println("方法");
	} 
}.method();

泛型

  • 泛型可以用来代表未知的数据类型

  • 泛型不能被继承!即:泛型 E 指定的类型必须一开始就被确定! 如:ArrayList<String> 确定了是String的类型。但是不能写成不确定的ArrayList<Object>

含泛型的类

修饰符 class 类名 <E>{
    private E name;
    //...
}

含泛型的方法

修饰符 [static] <E> void method(E e){
    System.out.println(e);
    //...
}

含泛型的接口

修饰符 interface 接口名<E>{
    [public abstract] void methodInterface(E e);
}
​
​
//使用方法一:在创建实现类的时候 直接指定泛型的数据类型
public class Impl implements 接口名<String>{
    @Override
    public void methodInterface(String str){
        //...
    }
}
​
​
//使用方法二:接口用什么泛型,实现类就使用什么泛型,创建对象的时候再确定数据类型
public class Impl<E> implements 接口名<E>{
    @Override
    public void methodInterface(E e){
        //...
    }
}
Impl<String> impl = new Impl<>();

泛型通配符

  • 泛型通配符和 E 很像,区别在于 泛型通配符 ? 只能作为未知的【参数】来使用,而不能当作数据类型来使用!

    即:?只能用于方法的参数传递数据,而不能向集合中存储数据

  • 总的来说,通配符可以在“遍历任意一个集合元素”的时候使用,作为一个参数在方法中传递

public static void printArray(ArrayList<?> list){
    Iterator<?> it = list.iterator();
    while(it.hasNext){
        Object o = it.next;
        //...
    }
}

  • 受限泛型(了解一下就好)

    泛型上限限定 格式 【 ? extends E】 //使用的泛型只能是E类型的 子类/本身

    泛型下限限定 格式 【 ? super F】 //使用的泛型只能是F类型的 父类/本身

下一篇介绍Java第二章 | OOP之继承

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Graskli

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值