目录
一.类与对象
1.this关键字
概念
this关键字表示当前对象的引用:
引用当前的实例变量
//无参数的构造方法
public Dog(){
this("旺旺",8); //传入什么参数类型就与哪个构造方法相匹配。
}
//有参数的构造方法
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public void fun(){
System.out.println(this.name+this.age);
}
上面代码中 Dog构造函数 和 fun方法中都是用了this关键字来访问当前类的对象,这样可以很清楚的指向那个对象的属性和方法。
this.name和this.age分别引用了当前对象的name和age实例变量
调用当前对象的构造函数
class Dog{ public String name; public int age; //无参数的构造方法 public Dog(){ this("旺旺",8); } //有参数的构造方法 public Dog(String name, int age) { this.name = name; this.age = age; } }
上面代码中 在无参的构造方法中使用this("旺旺",8), 表示调用当前类另一个带有俩个参数构造方法 ,并且this("旺旺",8);只能放在第一行,否则报错。
⚠️注意 :
- 不能在类中普通方法中调用this();否则又报错,
- this();需要放在当前类的构造方法中的第一行才可以,不然会编译报错不能通过。
总结:
1.this(); 是只能在当前类构造方法中使用,去调用当前类的其他构造方法。不能在普通的成员方法中使用。
2.只能放在第一行。如果不放在第一行,就不能通过编译
用this.在成员方法中调用其他成员方法
//有参数的构造方法 public Dog(String name, int age) { this.name = name; this.age = age; this.fun2("旺旺",15); } public void fun(){ System.out.println(this.name+this.age); } public void fun2(String name, int age){ this.fun();//在成员方法中调用其他成员方法 }
看到this.既可以在构造方法中去调用其他成员方法,也可以在成员方法中去调用其他成员方法。而且可以写在方法中的任意一行
2.super关键字
(super关键字可以说是 “ 为了代码的可读性 ”。记住不管什么时候想要访问子类对象的成员或者方法时使用 this. 访问父类对象的成员和方法时 使用 super.)
注意: 只有存在父类的情况下,才会用到super关键字
this(...)用于调用本类构造方法,
super(...)用于调用父类构造方法,
⚠️两种调用不能同时在构造方法中出现
在代码中
class Animal{//这是我们创建的父类Animal
//父类成员变量
public String name = "父类name";
public int age = 99; //注意父类中有姓名和年龄
//父类成员方法
public void eat(){
System.out.println(this.name + "父类正在吃饭");
}
public void sleep(){
System.out.println(this.name + "父类正在睡觉"); //父类中还有吃饭和睡觉
}
}
class Dog extends Animal{//这是我们创建的子类狗类。让它去继承Animal
public String name = "子类name";
public int height = 30;
public void show(){
System.out.println(name); //1.子类的
System.out.println(this.name); //2.子类的
System.out.println(super.name); //3.父类的
System.out.println("父类成员变量age:"+age); //4.父类的
System.out.println("父类成员变量age:"+this.age); //5.父类的
System.out.println("子类成员变量height:"+height); //6.子类的
System.out.println("子类成员变量height:"+this.height); //7.子类的
eat(); //8. //子类
this.eat(); //9. //子类
super.eat(); //10.父类
sleep(); //11.父类
this.sleep(); //12.父类
super.sleep(); //13.父类
wangWang(); //14.子类
this.wangWang(); //15.子类
}
public void eat(){
System.out.println(this.name + "子类正在吃饭");
}
void wangWang(){
System.out.println(this.name + "子类喜欢汪汪叫!");
}
}
public class GJiCheng {
public static void main(String[] args) {
//用Dog类实例化一个对象
System.out.println("--------------------------------");
Dog dog1 = new Dog();
dog1.show();
System.out.println("--------------------------------");
}
}
输出结果:
小结:
1.this访问的时候,既可以访问从父类继承下来的,也可以访问子类自己的2.super只能访问从父类继承过来的。在子类方法中,如果想要明确访问父类中成员时,借助super关键字即可。
3.当父类和子类有相同的成员变量或成员方法时,可以用super去访问从父类继承过来的,不用super 则访问的是子类自己的那个成员变量或成员方法。
4.super只是一个关键字。提高代码的可读性,让别人轻松知道这是访问父类中的
注意: 当父类与子类有相同的方法名但是参数不同的情况下,我们传入什么参数匹配到那个方法,那么就会访问到哪个方法.(方法的重载)
总结super和this的区别
相同点:
- 都是java的关键字
- 都可以在成员方法来访问:成员变量和调用其他的成员方法
- 在构造方法调用是,必须在构造方法的第一条语句执行,并且不可以同时存在
- 只能在类中的非静态方法中使用,来访问非静态成员和非静态方法
不同点:
- this关键字只能对当前对象的引用,super关键字只能对父类对象的引用(继承下来的非静态成员和非静态方法)
- 在非静态成员方法中,this用来访问当前类的方法和属性,super用来访问父类继承下来的方法和属性
- 在构造方法中,this()用来调用当前类的其他构造方法,super()用来调用父类构造方法,并且两种关键字不可以在构造方法中同时出现
- 父类中存在带参的构造方法时,子类的构造方法一定存在super()的调用,用户没有写,编译器也会增加,但是this()的调用需要用户来编写。
二 封装
1.封装的概念
- 封装从语法上来说 就是被private关键字修饰的成员变量或者方法 只能在当前类使用
- 封装是指把一个对象的状态信息(也就是属性)隐藏在对象内部,不允许外部对象直接访问对象的内部信息,仅对外公开接口来和对象进行 交互
2.访问限定符
NO | 范围 | private | default | protected | public |
1 | 同一个包中的同一类 | ✅ | ✅ | ✅ | ✅ |
2 | 同一个包中的不同类 | ✅ | ✅ | ✅ | |
3 | 不同包的中的子类 | ✅ | ✅ | ||
4 | 不同包中的非子类 | ✅ |
- public:可以理解为一个人的外貌特征,谁都可以看得到
- default: 对于自己家族中(同一个包中)不是什么秘密,对于其他人来说就是隐私了
- private:只有自己知道,其他人都不知道
- default权限指:什么都不写时的默认权限
建议:一般情况下成员变量设置为private,成员方法设置为public
3.常见的包:
1. java.lang: 系统常用基础类 (String 、 Object), 此包从 JDK1.1 后自动导入。2. java.lang.reflect:java 反射编程包 ;3. java.net: 进行网络编程开发包。4. java.sql: 进行数据库开发的支持包。5. java.util: 是 java 提供的工具程序包。 ( 集合类等 ) 非常重要6. java.io:I/O 编程开发包。
4 static成员
1.static修饰成员变量
- 不属于某个具体的对象,是类的属性,所有对象共享的,不存储在某个对象的空间中
- 既可以通过类访问,也可以通过对象访问,推荐使用类名访问, 更好的区分 静态变量
- 类变量存储在方法区当中
- 生命周期伴随类的一生( 随类的加载而创建,随类卸载而销毁)
public class Static {
private static String name="静态";
private int age;
public static void fun(){
System.out.println("调用静态方法");
}
public void fun1(){
System.out.println("调用普通方法");
}
public static void main(String[] args) {
Static aStatic = new Static();
Static aStatic2 = new Static();
Static aStatic3 = new Static();
//创建Static实例化 用对象来调用静态成员变量
System.out.println(aStatic2.name);
System.out.println(aStatic3.name);
System.out.println(aStatic.name);
//使用类名调用静态成员变量
System.out.println(Static.name);
}
}
2.static修饰成员方法
一般类中的数据成员都设置为private,而成员方法设置为public,
被static修饰的成员方法称为静态成员方法,是类的方法,不是某个对象所特有的
public class Static {
public static void fun(){
System.out.println("调用静态方法");
}
public void fun1(){
System.out.println("调用普通方法");
}
public static void main(String[] args) {
Static aStatic = new Static();
//创建Static实例化 用对象来调用静态方法
aStatic.fun();
//使用类名调用静态方法
Static.fun();
}
}
静态方法的特征:
- 在静态方法中 不可以调用非静态成员变量 会报错,也不可以调用非成员静态方法
- 可以使用类名调用,也可以使用对象调用 , 推荐使用类名
-
不属于某个具体的对象,是类方法
5.内部类
简述
//Static属于外部类 public class Static { //student 属于内部类 class student{ }
student类是Static类中新创建的类 属于内部类
注意 :定义在class 类名{}花括号外部的,即使是在一个文件里,都不能称为内部类
class student{ } class teacher{ }
// A 和 B是两个独立的类,彼此之前没有关系
5.1 内部类的分类
//Static属于外部类
public class Static {
//未被static修饰————实例内部类
class student{
}
//被static修饰————静态内部类
static class teacher{
}
public static void fun(){
class Innerclass{// 在方法定义的内部类————局部内部类
}
}
}
5.2实例内部类
没有被static修饰的内部成员类称为静态内部类
public class OutClass {
private int a;
static int b;
int c;
public void methodA(){
a = 10;
System.out.println(a);
}
public static void methodB(){
System.out.println(b);
}
// 实例内部类:未被static修饰
class InnerClass{
int c;
public void methodInner(){
// 在实例内部类中可以直接访问外部类中:任意访问限定符修饰的成员
a = 100;
b =200;
methodA();
methodB();
// 如果外部类和实例内部类中具有相同名称成员时,优先访问的是内部类自己的
c = 300;
System.out.println(c);
// 如果要访问外部类同名成员时候,必须:外部类名称.this.同名成员名字
OutClass.this.c = 400;
System.out.println(OutClass.this.c);
}
}
public static void main(String[] args) {
// 外部类:对象创建 以及 成员访问
OutClass outClass = new OutClass();
System.out.println(outClass.a);
System.out.println(OutClass.b);
System.out.println(outClass.c);
outClass.methodA();
outClass.methodB();
System.out.println("=============实例内部类的访问=============");
// 要访问实例内部类中成员,必须要创建实例内部类的对象
// 而普通内部类定义与外部类成员定义位置相同,因此创建实例内部类对象时必须借助外部类
// 创建实例内部类对象
OutClass.InnerClass innerClass1 = new OutClass().new InnerClass();
// 上述语法比较怪异,也可以先将外部类对象先创建出来,然后再创建实例内部类对象
OutClass.InnerClass innerClass2 = outClass.new InnerClass();
innerClass2.methodInner();
}
- 在实例内部类方法中可直接访问外部类中的任何成员
- 实例内部类所处的位置与外部类成员位置相同,因此也受public、private等访问限定符的约束
- 在实例内部类方法中访问同名的成员时,优先访问自己的,如果要访问外部类同名的成员,必须:外部类名称.this.同名成员 来访问
- 实例内部类对象必须在先有外部类对象前提下才能创建
- 实例内部类的非静态方法中包含了一个指向外部类对象的引用
- 外部类中,不能直接访问实例内部类中的成员,如果要访问必须先要创建内部类的对象。
5.3静态内部类
public class OutClass {
private int a;
static int b;
public void methodA(){
a = 10;
System.out.println(a);
}
public static void methodB(){
System.out.println(b);
}
// 静态内部类:被static修饰的成员内部类
static class InnerClass{
public void methodInner(){
// 在内部类中只能访问外部类的静态成员
// a = 100; // 编译失败,因为a不是类成员变量
b =200;
// methodA(); // 编译失败,因为methodB()不是类成员方法
methodB();
}
}
public static void main(String[] args) {
// 静态内部类对象创建 & 成员访问
OutClass.InnerClass innerClass = new OutClass.InnerClass();
innerClass.methodInner();
}
}
5.4 局部内部类
定义在外部类的方法中的内部类或者{}中———局部内部类
public class OutClass {
int a = 10;
public void method(){
int b = 10;
// 局部内部类:定义在方法体内部
// 不能被public、static等访问限定符修饰
class InnerClass{
public void methodInnerClass(){
System.out.println(a);
System.out.println(b);
}
}
// 只能在该方法体内部使用,其他位置都不能用
InnerClass innerClass = new InnerClass();
innerClass.methodInnerClass();
}
public static void main(String[] args) {
// OutClass.InnerClass innerClass = null; 编译失败
}
}
5.5匿名内部类
在Java中,匿名内部类是一种没有名字的局部内部类,它允许我们在使用类的同时定义和实例化它。通常情况下,匿名内部类用于创建一次性的类实例,它可以实现接口或继承抽象类,并且可以覆盖父类或接口的方法。
- 没有(或者不需要)命名来初始化类,就称为匿名内部类。
- 在这四种内部类中,以后的工作可能遇到最多的是匿名内部类,所以说匿名内部类是最常用的一种内部类。
class teacher{
private String name ;
void eat(){
System.out.println("hhh");
}
}
//Static属于外部类
public class Static {
public static void main(String[] args) {
new teacher(){
@Override
void eat() { //实现匿名内部类 并重写eat方法
System.out.println("匿名内部类");
}
}.eat();
new teacher().eat(); //创建匿名对象
}
}
如何使用匿名内部类:
1.匿名内部类需要依托于其他类或者接口来创建
- 如果依托的是类,那么创建出来的匿名内部类就默认是这个类的子类
- 如果依托的是接口,那么创建出来的匿名内部类就默认是这个接口的实现类。
2.匿名内部类的声明必须是在使用new关键字的时候
- 匿名内部类的声明及创建对象必须一气呵成,并且之后能反复使用,因为没有名字。
匿名内部类特点:
- 匿名内部类除了依托的类或接口之外,不能指定继承或者实现其他类或接口,同时也不能被其他类所继承,因为没有名字。
- 匿名内部中,我们不能写出其构造器,因为没有名字。
- 匿名内部中,除了重写上面的方法外,一般不会再写其他独有的方法,因为从外部不能直接调用到。(间接是调用到的)
interface Work {
void doWork();
}
public class AnonymousOuterClass {
private String name = "AnonymousOuterClass";
private static int age = 21;
public void say() {
System.out.println("Say...");
}
public static void go() {
System.out.println("Go...");
}
public void test() {
final int i = 90;
Work w = new Work() {
@Override
public void doWork() {
// 打印外部类的属性
System.out.println(AnonymousOuterClass.this.name);
System.out.println(AnonymousOuterClass.age);
// 调用外部类的方法实例方法
AnonymousOuterClass.this.say();
// 调用外部类的方法静态方法
AnonymousOuterClass.go();
// 打印方法里面定义的常量
System.out.println(i);
}
};
w.doWork();
}
}
class Test {
public static void main(String[] args) {
new AnonymousOuterClass().test();
}
}
使用匿名内部类实现接口就会变得非常简单
interface Test1 {
public void method();
}
public class Test {
public static void main(String[] args) {
//如果我们需要使用接口中的方法,我们只需要走一步,就是使用匿名内部类,直接将其 类的对象创建出来。
new Test1() {
public void method() {
System.out.println("实现了Test接口的方法");
}
}.method();
}
}