JAVA面向对象(1)

类的初始化和实例化的区别

类的初始化:是完成程序执行前的准备工作。在这个阶段,静态的(变量,方法,代码块)会被执行。同时在会开辟一块存储空间用来存放静态的数据。初始化只在类加载的时候执行一次。

类的实例化:是指创建一个对象的过程。这个过程中会在堆中开辟内存,将一些非静态的方法,变量存放在里面。在程序执行的过程中,可以创建多个对象,既多次实例化。每次实例化都会开辟一块新的内存。

比如说我们以洗衣服为例:

1)假设此时我们要洗一件衣服,我们如果说要是面向过程的话,那么就是

第一步:拿一个盆子

第二步:放水

第三步:放衣服

第四步:放洗衣粉

第五步:手搓

第六步:换水

第七步:拧干

第八步:晒衣服

那么整个洗衣服的过程就是:人把衣服放进洗衣机,倒入洗衣粉,启动洗衣机,洗衣机就会完成整个洗衣服的过程并且会甩干

如果说以面向对象的思想来进行凯带着一件事情的话:

在这个洗衣服的过程中,我们需要用到四个对象,人,衣服,洗衣粉,洗衣机,整个过程是靠人,衣服,洗衣粉,洗衣机四个对象进行相互交互来进行完成这个过程的,人这个对象是不需要关心洗衣机是如何进行洗衣服,如何进行甩干的

面向对象和面向过程: 

1)C语言是面向过程的,关注的是过程,分析出解决问题的步骤,通过函数调用来进行逐步解决问题
2)但是Java是面向对象的,关注的是对象,将同一个事情拆分成不同的对象,靠对象之间来相互配合进行完成一件事情今年

3)面向过程注重的是过程,也就是参与过程中所有所涉及到的行为,就是功能,但是面向对象注重的是对象,也就是说参与过程所涉及到的主体,通过逻辑将一个个的功能连接起来
4)面向对象:打开冰箱门,把大象进行存储进去储存,关闭冰箱门都是对冰箱进行的操作,这是对冰箱的一种行为;但是冰箱就是一个对象,所以只要冰箱所具备的功能,就都需要被定义到冰箱中;
5)面向对象是思考问题的一种方式,是一种思想,面向对象设计有一个重要的经验:谁拥有这些数据,谁就对外提供操作这些数据(私有的方法),被动的一方是数据的拥有者,主动的一方是执行者
6)类就是一类对象的统称,对象就是这一类具体化的一个实例,通过一个类可以实例化多个对象,实例化出来的对象,占用实际的物理空间,存储类成员变量

Java是一种纯面向对象的语言,面向对象是解决问题的一种重要思想,主要是依赖对象之间的交互来完成一件事情

注意:在对象里面是不存在方法的,方法是不占内存的,只有说调用了方法,才会在栈上面开辟内存

一:成员变量(属性字段):定义在方法外的但是类内的字段和属性,分为普通成员变量和静态成员变量:

普通成员变量:引用.字段,所以说是依靠对象的引用来进行访问的,如果我们的成员变量没有赋初值,那么访问的时候打印的就是默认值,但是局部变量在初始化的时候一定要进行赋值,否则再初始化的时候,程序会发生报错,每一个对象都有自己的默认的成员变量,我们所有的代码片段都在方法区里面

咱们的成员变量没有进行初始化的时候,默认值就是对应的初始值

普通的成员变量是属于对象的

整形:byte,short,int,long默认值是0
字符型:double,float默认是0.0
布尔类型:boolean:默认是false
引用数据类型:数组,接口他们的默认值都是空
字符类型:char--->/u000000

静态成员变量:引用.字段或者是类名.字段,叫做类变量,静态成员变量也在方法区里面,实质上不需要对象的引用来进行访问

class Student{
    public String name;
    public int age;//这是一个普通成员变量
    public static int count=9;//这是一个静态成员变量
    public void run()
    {
        System.out.println(1);
    }
public static void start()
    {
        System.out.println(2);
    }
}
new Student()在堆上,但是指向new Student()的实例(引用)在栈上;

注意:上面的person是一个变量,不是地址,只不过这个变量,里面存放的是地址,这个变量也叫做引用,这个变量类型就是Person类型

二:成员方法--->行为

普通成员方法和静态成员方法,方法的这些片段在咱们的方法区里面,我们只要调用这个方法,在栈上面就要为这个方法开辟内存;

静态成员方法也是依据类名.方法名来进行访问

注意:在我们普通的方法内部,是不可以定义静态的变量

1)static修饰的变量是属于类变量是在方法区里面,而方法是属于对象的,静态成员变量赋值的时候通过

类名.变量=具体的值

2)普通成员方法调用,需要对象的引用来进行访问,如果可以定义static,就可以通过类名来进行访问,而成员方法调用还需要new一个对象呢

3)在我们静态成员方法里面也是不可以进行定义static类型的变量,因为static类型的变量是属于类的,如果static定义的变量在方法里面,这就是属于方法的,这也是不可以的,总结:静态的成员变量是不可以在方法中定义的

4)在普通方法内部是可以调用静态方法的,但是在静态方法里面是不可以调用普通方法的,所以静态方法里面只能调静态方法,如果实在想要在静态方法里面调用普通的方法,那就需要在静态方法里面new对象,再通过这个对象去访问这个普通的方法

在静态方法里面不可以访问普通的成员变量和方法,也就是不能直接访问非静态的数据成员和成员方法,也不可以使用this和super关键字来进行访问成员变量和成员方法

5)一个引用不可以同时指向多个对象,引用不一定是在栈上面,也可以在堆上面

6)我们在一个类中的普通的方法可以通过this.静态成员变量来进行访问这个变量,也是可以通过类名.变量来进行访问

7)static修饰的类变量的生命周期伴随着类的一生,随着类的加载进行创建,随着类的卸载而进行销毁

package Demo;
class Person{
    public String name;
    public int age;
}
public class TestDemo {
    Person person=new Person();//在堆上面
    public static void main(String[] args) {
TestDemo testDemo=new TestDemo();
    }
}

上面的这些引用全部在JAVA虚拟机栈

static修饰的关键字的作用:

1)被static修饰的成员变量和成员方法独立于该类的任何对象,他是和类紧紧联系在一起的
被类所有的实例所共享,他是永远在方法区的,它不属于类的对象,但是属于类;
2)这也就是说不管创建多少对象,static修饰的变量只占有一块内存。

3)被static修饰的方法称之为静态成员方法,静态方法属于类,而不属于类的对象,静态方法可以访问静态数据成员,并且可以更改静态数据成员的值,但是不可以定义一个静态成员变量,所以说静态成员通常是通过静态方法来进行访问的

4)Java中,被static修饰的 class 都是 内部类,static class 是可以被继承的,但是被static修饰的方法是不可以重写的

5)内部类就是定义到类内部的类:

我们再给内部类加上static关键字之后,当前创建内部类的实例就不会依托于外部类的实例

如果我们不给内部类加上static就必须先把外部类的实例进行创建出来,在进行创建内部类的实例

1)静态方法和实例没有关系,而是和类相关,静态方法不能直接访问非静态数据成员和普通成员方法;

2)this和super两个关键字是不可以在静态上下文进行使用,因为this是当前对象的引用,super是当前父类实例的引用;

3)这个变量放在哪里和是否被final修饰没有什么关系

下面我们来进行讲解一下类的初始化顺序: 

1.普通类(这里面是没有继承关系的)

一:静态部分:

1)静态部分(静态变量,常量,静态代码块)

2)在我们的类加载阶段,类中存在多个静态部分,会按照顺序进行执行

3)静态代码块只会执行一次,况且静态的变量,常量只会创建一份

二:非静态部分:(实例变量,常量,实例代码块)

当我们有对象创建的时候才会执行,按顺序执行

三:我们最后会执行构造方法,当有对象创建的时候才会执行

2.派生类的初始化顺序:

一:静态部分(静态变量,常量,静态代码块)

1)父类静态代码块会优于子类的静态代码块执行,况且最早执行

2)只有当我们的第一次进行实例化子类对象的时候,父类和子类的静态部分才会执行

3)父类非静态部分(实例变量,常量,实例代码块和父类的构造方法)

4)子类非静态部分(实例变量,常量,实例代码块和子类的构造方法)

重写ToString方法:println会默认调用父类的ToString

1)public void println(Object x) {
        String s = String.valueOf(x);
        synchronized (this) {
            print(s);
            newLine();
        }
    }
2)public static String valueOf(Object obj) {
        return (obj == null) ? "null" : obj.toString();
    }
3) public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

如果不加上this,那么就会有局部变量优先使用的原则

封装:

1)是将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅仅对外提供接口来和对象进行交互

2)我们通常把成员变量设置成private,成员方法设置成public,我们对类的内部的实现细节进行了隐藏和封装,我们对外只能提供一些公开的方法供其他用户来进行访问,没有必要的属性不用公开在类外

3)不必要的公开里面的数据成员或方法,使用private进行修饰,为了更安全,它会提供公有的方法,对于类的调用者来说,不需要知道具体的实现细节,只需要调用这些共有的方法即可,降低了代码的管理复杂度

4)这就类似于说对于电脑这样一个复杂的设备,我们给用户提供的只有开关机,通过键盘进行输入,显示器,USB插孔,让我们的用户与计算机完成交互;

5)但是我们实际上,电脑真正的工作就是CPU显卡,还有一些硬件;用户只需要知道,怎么开机,怎么通过键盘和鼠标与用户进行交互就可以了,而不需要知道CPU内部是如何进行设计的,主板上面线路是怎么布局的;因此我们的计算机厂商进行出厂的时候,可以将内部的实现细节隐藏起来,仅仅对外提供开关机,鼠标和插口,让用户和计算机实现交互

一:构造方法:实例化对象的时候,一定会调用构造方法,当我们的构造方法调用完成之后,对象真正的产生了

是一个特殊的成员方法,他的方法名称和类名是相同的,而且没有返回值,在我们进行创建实例化对象的时候,由我们的编译器自动进行调用,并且在整个对象的生命周期里面只进行调用一次,况且可以提供不同版本的构造方法

我们的构造方法的作用就是给对象中的成员进行初始化,但是并不会负责给对象开辟空间

可以这么说,当我们的构造方法调用完成之后,咱们的对象实际上才产生了,对象的产生一定是要进行调用构造方法

1)每一个类中至少存在一个构造方法,当你没有提供任何构造方法的时候,编译器会自动提供一个不带有参数的构造方法,在构造方法中,我们可以通过this来进行调用其他构造方法来进行简化代码

2)当你提供了构造方法,编译器就不会再生成构造方法了

3)构造方法之间是可以构成重载

4)我们可以在无参的构造方法中调用具有两个参数的构造方法,我们通过this()调用其他的构造方法的时候,必须是放在构造方法里面,而且必须是第一行

4)注意:
1)我们在构造方法里面,我们通过this(....)去调用其他构造方法的时候,我们的这条语句必须是构造方法中的第一条语句
2)我们的多个构造方法之间不可以进行相互调用,我掉你,你调用我,不能循环调用,不能形成环

class Person{
    public String name;
    public int age;
    public Person(String name)
    {
        this(90);
        System.out.println(1);
    }
    public Person(int age){
        this("abc");
    }
}

1)我们在继承的基础上面,子类对象在进行构造的时候,需要先进行调用基类的构造方法,然后再去执行子类的构造方法 

2)我们在子类的构造方法里面,我们虽然并没有写有关于基类构造的代码,但是当我们在构建子类对象的时候,先执行基类的构造方法,然后再去执行子类的构造方法

3)我们的原因在于,子类对象中成员是由两部分组成的,基类继承下来的和子类新增加的部分,父类和子类,肯定是现有父再有子,所以我们在进行构建子类对象的时候·,我们的子类对象肯定要先调用基类的构造方法,将我们的基类的继承下来的成员进行构造完整,然后再进行完成子类自己的构造,再将子类的新增加的成员初始化完整

一:如果说我们的父类显示无参或者默认的构造方法,在我们子类的构造方法的第一行默认会含有隐含的super()调用,即调用基类的构造方法:

 static class Father{
      public Father()
      {
          System.out.println("我是父类的构造方法");
      }
  }
 static class Child extends Father{
      public Child()
      {
            super();
//注意:在我们的子类的构造方法里面会默认调用基类的无参构造方法,super(),当我们的用户没有写的时候,编译器会自动进行添加的,况且super()必须是子类构造方法中的第一条语句
          System.out.println("我是子类的构造方法");
      }
  }
    public static void main(String[] args) {
        Child child=new Child();
    }

二:如果父类构造方法是含有参数的,那么我们需要用户显式定义构造方法,用super()的时候,必须出现在第一条语句

this访问成员变量:this.data;

this访问成员方法:this.func();

this访问构造方法:this();

一个对象的产生(new的过程),要经过几步?

1)为对象分配合适的内存空间

2)调用合适的构造方法(可能有多个构造方法)

class Student{
    public String username;
    public String password;
    public int age;
    public void SetData(String name,String word,int IntAge){
        username=name;
        word=word;
        age=IntAge;
    }
    public void run(){
        System.out.println(username);
        System.out.println(password);
        System.out.println(age);
    }
  public void start(){
       this.run();
    }
}
public class Solution{
    public static void main(String[] args) {
        Student student1=new Student();
        Student student2=new Student();
        Student student3=new Student();
        student1.SetData("李佳伟","张三",10);
        student2.SetData("周云刚","王五",20);
        student3.SetData("霍飞跃","90",30);
        student1.run();
        student2.run();
        student3.run();
    }
}

 这两个方法如何知道他们打印的是哪一个对象?他们进行设置的是哪一个对象?

1)谁进行调用这个方法,设置的就是哪一个对象

2)每一个方法的第一个参数都默认了一个隐藏对象:类的名字 this,谁调用这个方法谁就是this

this关键字的用法:

在我们的成员方法当中每一个函数的前面有一个默认的参数(类名 this),谁调用当前的这个方法,谁就是this

class Student{
    public String username;
    public String password;
    public int age;
   public Student(){
       this("我是李家伟","今年18岁");//必须放在构造方法里面,况且必须是第一行,在构造方法里面调用其他的构造方法
       System.out.println("我是带有两个参数的构造方法");
   }
   public Student(String username,String password){
       this.username=username;
       this.password=password;
   }
}
public class Solution{
    public static void main(String[] args) {
        Student student1=new Student();
        Student student2=new Student();
        Student student3=new Student();
    }
}
class Solution{
    public void run(Solution this){
    }
}

定义:我们的this引用是成员方法的参数之一,不需要用户进行传递实现,是由我们的编译器来进行自动完成,也就是说当前这个参数用户是看不到的,但是用户可以使用这个参数,况且this只能在成员方法中进行使用

1)this()调用自己的构造方法,使用放在第一行,况且只能在构造方法中适用,不能在其他方法中使用

2)this.data调用自己的属性,如果不加this,那么编译器就会认为局部变量优先,无法通过构造方法来对成员变量进行赋值

3)this.func()调用当前对象的方法

解决的方法就是当我们的方法形参名和我们的成员变量名相同,尤其是在我们的构造方法里面,形参名和我们的类的字段名相同的时候也就是构造方法的形参名和成员变量的名字重复了之后,我们就可以用到this引用了

我们的this引用指向当前对象(成员方法运行的时候调用该成员方法的对象)

在成员方法中所有对成员变量的操作,都是通过该引用去访问

this是成员方法中第一个隐藏的参数,编译器会自动进行传递,在成员方法执行的时候,编译器会负责将调用成员方法的引用传递给该成员方法,由this来负责进行接收

当我们进行new关键字进行操作的时候, 虽然在程序方面只是一条简单的语句,但是在JVM层面还是要做很多事情的:

1)检测对象对应的类是否加载了,如果说没有进行加载,那么直接进行类加载

2)为对象分配内存空间

3)处理并发安全问题,比如说多个线程同时申请对象,JVM要进行保证对象分配的空间不冲突

4)初始化所进行分配的空间,就是对象空间被申请好了之后,对象中的成员已经被设置好了初始值

5)设置对象头信息

6)调用构造方法,给对象中的各个成员赋值

封装的主要意义就是说对外隐藏内部类的实现细节,增强程序的安全性

做题把循环输入写上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值