Java知识点总结【3】类和对象

1.什么是面向过程,什么是面向对象

面向过程:要按照业务流程按部就班的来组织代码。

面向对象:要先把业务中的一些概念先提取出来,作为“对象”,然后把对象的每个属性和行为都安排好,然后再去组织业务流程。

2.什么是类和对象

Java中的内置类型不够用,所以根据自己的实际需要创建出一些类型,由自定义的类型创建出来的变量就是对象。类相当于图纸,对象是根据图纸盖出来的房子。

3.类的定义和使用

1)定义示例:

class Cat {
    public String name;  //姓名
    public int age;   //年龄
    public String gender;  //性别
    
    public void eat(){
        System.out.println("小猫正在吃");
    }
    public void sleep(){
        System.out.println("小猫正在睡觉");
    }

}

class为定义类的关键字,Cat为类的名字,{}中为类的主体。

其中name,age,gender称为成员属性/成员变量,这几个变量信息是对类的描述

eat(),sleep()称为成员方法,主要说明类有什么功能

注意:

  • 类名使用大驼峰
  • 一个.java文件可以包含多个类
  • 一个.java文件至少得有一个class是public修饰的
  • 被public关键字修饰的类名,必须和.java文件的名字相同(大小写敏感)

2)类的实例化

实例化相当于根据图纸,建造出房子。使用new 关键字来创建对象。

Cat cat=new Cat();
cat.eat();
cat.sleep();

4.成员变量的初始化

1)默认初始化

注意分清什么是成员变量,什么是局部变量(类中的是成员变量,方法中的是局部变量)。局部变量如果不初始化,编译会报错。如果针对对象中的成员变量没有显示的进行初始化,此时存在一个默认值。

规则:

  • 数字类型(包括整数和浮点数)默认初始化为0
  • 布尔类型,默认初始化为false
  • 引用类型(String,数组,类),默认初始化为null
  • char类型,默认初始化为'\u000'

示例:

class Init{
    int a;
    long b;
    double c;
    String d;
    boolean e;

}
public class Blog{
    public static void main(String[] args) {
        Init init=new Init();
        System.out.println(init.a);
        System.out.println(init.b);
        System.out.println(init.c);
        System.out.println(init.d);
        System.out.println(init.e);
    }

}

2)就地初始化

这个不难理解,直接看下面的例子就懂了~

class Init{
    int a=2;
    long b=20;
    double c=1.0;
    String d="";
    boolean e=true;

}

3)构造方法初始化

构造方法的特点

  • 构造方法的名字名和类名相同
  • 不需要写return语句
  • 不需要手动显示的调用,而是在new的时候,就会被自动的调用
  • 构造方法支持重载

使用构造方法初始化,比前面两种初始化方式更灵活强大

  • 构造方法可以传递一些参数,动态的获取到要针对对象初始化的值
  • 构造方法可以支持重载,可以有多个构造方法,不同的构造方法所支持的参数的个数或者类型是不同的。正因为这样的重载,就可以通过不同的方式来针对某个对象进行初始化。

示例:

class Init{
    String name;
    public Init(String name){
        this.name=name;
    }
}
public class Blog{
    public static void main(String[] args) {
        Init init=new Init("构造方法初始化示例");
        System.out.println(init.name);
    }

}

结果

分析:在new对象的时候,就会自动调用构造方法,在传入的参数的时候,形参的name和当前创建的对象的成员变量名name重名了,所以编译器无法区分把形参name赋值给形参还是赋值给当前对象的成员变量name,所以可以使用this关键字来区分,表示当前对象,this相当于“我”,看当前的方法是被哪个对象调用的,this就表示是谁。所以通过传入构造的参数就可以成功初始化我们的成员变量name,最终打印出初始化的成果~

关于this的一些注意事项:this只能在成员变量中使用,在构造方法中,必须放在第一行,且只能调用一个.this()的形式调用当前类的另外一个构造方法。

4)代码块初始化

这个也是看下面的例子也就会了,使用的比较少,但是也有特殊的作用~

class Init{
    String name;
    {
        System.out.println("你好呀~我是代码块初始化时打印的哦~~");
        name="hello";
    }
}
public class Blog{
    public static void main(String[] args) {
        Init init=new Init();
        System.out.println(init.name);

    }

}

结果

5)实例化对象的初始化执行顺序

默认初始化->就地初始化和代码块初始化谁先出现先执行谁->构造方法初始化

5.toString

任何一个类里面都可以有toString这个方法,通过这个方法,就可以把一个对象转成一个String,转成String之后,就可以把String打印出来,或者保存在文件中,或者通过网络发送出去...

toString这个方法一般不需要显式调用(显式调用也完全可以),不写显式调用的时候,当代码中把这个对象当成字符串来使用的场景中,就会自动触发toString(比如System.out.println())

示例:

class Init{
    int year;
    int month;
    int day;
    //构造方法
    public Init(int year,int month,int day){
        this.year=year;
        this.month=month;
        this.day=day;
    }
    //toString方法
    public String toString(){
        return this.year+"/"+this.month+"/"+this.day;
    }
}
public class Blog{
    public static void main(String[] args) {
        Init init=new Init(2020,1,20);
        System.out.println(init);

    }

}

结果

6.关于static

如果一个成员没有被static修饰,这是一个对象的属性/成员/字段

如果一个成员被static修饰了,这就是这个类的属性/成员/字段,使用的时候要用类名.XX的方法使用,只有一份(就相当于只有一份图纸,图纸也有自己的属性,比例尺呀啥的~,不会因为根据图纸创建出的对象的不同而导致图纸的属性变了)

class Person{
    String name="一颗苹果";
    static String project="Java";
    }
public class Blog{
    public static void main(String[] args) {
        System.out.println(Person.project);
    }

}

7.访问限定符

属性或者方法前可加这些限定符:

  • private:类内部可访问
  • default:同包之间访问
  • protected:不止同包,而且可被其他包中的子类访问
  • public:可在类外部访问

类前面只能加public或者啥都不加

该使用哪种访问权限?一般是希望代码封装程度更好一些,能不被外面知道的东西,就尽量别暴露出去,能使用private尽量用private。

8.代码块

是使用{}定义的一段代码,有四种:

1)普通代码块:定义在方法中的代码块

2)构造块:定义在类中的代码块(不加修饰符),一般用来初始化成员变量,上面举栗子了~

3)静态块:使用static定义的代码块,一般用于初始化静态成员属性

class Person{
    static String name;
    static{
        name="一颗苹果";
    }
}
public class Blog{
    public static void main(String[] args) {
        System.out.println(Person.name);
    }

}

注意:静态代码块不管生成多少个对象,其只会执行一次,且是最先执行的。静态代码块执行完毕后, 实例代码块(构造块)执行,再然后是构造函数执行。

static修饰的代码块执行始终在普通代码块之前,static代码块是在类加载的时候执行的,普通代码块是在创建实例的时候执行的,类加载始终是在创建实例之前(类加载只进行一次)

4)同步代码块

9.内部类

将一个类定义在另一个类中或者一个方法中里面,这样的类称为内部类。

1)静态内部类

static修饰,表示是类相关的

public class Blog{

    static class B{
    }

    public static void main(String[] args) {
        B b1=new Blog.B();
        B b2=new B();//也可以省略前面的绑定
    }

}

和静态变量静态方法类似,静态内部类也是和当前类(Blog)绑定的,使用的时候也是使用当前的类Blog调用的。

2)匿名内部类(相对比较常用)

是在一个方法或者代码块中定义的类,没有显示申明类的名称

public class Blog{
    public static void main(String[] args) {
//      定一个匿名内部类
        A a=new A(){

        };

    }
}
class A{

}

可以看到上面,A a=new A()后面有一个{},表示可以重写方法,对于A中的方法进行重写,其实也就相当于重新创建了一个类(重写之后的类的功能和之前的类的功能不同了),但是这个类我们并没有给它起名字,所以就叫做匿名内部类。
 

public class Test {
    public static void main(String[] args) {
        A1 a=new A1(){
           public String func(String s){
               System.out.println("hello");
               return s;
           }
        };
        System.out.println(a.func("world"));
    }
}
class A1{
    public String func(String s){
        return s;
    }
}

分析:

上面的代码中,我们可以看到有一个类A1,它里面有一个方法func(),功能是将调用时传入的参数打印出来。但是我们在main方法中,实际想要根据A1创建对象时,希望它的实例调用func这个方法时不仅能实现原本的func()的功能,还期望它有别的功能,如上例中,还能打印出"hello",所以就要对A1中的func进行重写,于是我们在A1 a=new A1()后面加上大括号,里面写我们重写的内容,此时的a调用func方法的结果就如下所示:

经常用在需要实例化某个对象,但需要重写方法时,比如new接口,抽象类就是使用匿名内部类较多的方式~~

3)成员内部类

public class Test{
    //定义一个成员内部类C
    public class C{
        
    }
    public static void main(String[] args) {
        C c=new Test().new C();
    }
}

4)局部内部类(没啥用)

局部内部类的作用域和局部变量的作用域相似,在方法或代码段中定义,作用域和匿名内部类的作用域相同。

public class Test {
    public static void main(String[] args) {
        class D extends A{
    }
    System.out.println(new D());
    }
}
class A{
}

和匿名内部类相似,只是显示申明了名字

10.类和对象的内存布局

JVM中的内存区域除了堆和栈之外,还有一个非常重要的区域,方法区。这些是JVM自己从系统申请过来的内存的进一步的划分。

栈:方法和方法之间的调用关系

堆:new出来的对象/实例

方法区:存的是一个一个的“类相关的信息”(每个类的方法的二进制的指令也是在这里),对于属性来说,如果属性是一个实例属性,那么不在方法区,而是跟着实例走(实例一般在堆上),如果一个属性是一个类属性(static),那么也就在方法区中。对于方法来说,不管是加static还是不加,对应的内容都是在方法区中。

猜你喜欢

转载自blog.csdn.net/weixin_43939602/article/details/112792844
今日推荐