目录
面向过程和面向对象区别
类和对象的概述
类的属性和方法
构造方法及其重载
基本数据类型传递和引用数据类型传递的区别
this关键字详解
static关键字详解
局部代码块,构造代码块,静态代码块
package和import详解
例如:洗衣服
面向过程:拿一个盆 -> 把衣服扔进去 -> 倒水和洗衣液 -> 洗衣服 -> 用清水洗两遍 -> 拧干衣服 -> 晾起来
面向对象:将衣服扔进洗衣机 -> 放水和洗衣液 -> 启动洗衣机 -> 将衣服晾起来
区别:面向过程侧重于每一个步骤具体怎么做
面向对象:侧重于结果,不用管它内部是怎么实现的,只要实现了功能就可以了
类其实就是一个模板,对象就是根据这个模板创建出来的。一个类可以创建出多个对象,而一个对象只能是由一个类创建出来的。
eg:工厂里的模具就相当于类,根据模具生产出来的产品就是一个一个的对象。这些产品对象都具有相似的特征,在之后我们把这些相似的特征叫做属性。
这个讲起来比较抽象,所以我就用例子来说明一下什么叫类的属性,什么叫类的方法;
如图可以很清晰的知道,属性也就是学生所具有的特征,比如姓名,年龄,性别;
方法也就是学生的行为,比如学生具有学习的行为等等;
修饰符 类名(形参列表){
}
隐式构造方法:在一个类中,当你没有手动编写构造方法时,系统会有一个默认的无参构造方法;
显示构造方法:在一个类中,当你手动编写了构造方法时,系统默认的无参构造方法将会失效;所以建议在你手动编写了构造方法时,顺便写一个无参的构造方法;
构造方法的重载与普通方法的重载是一样的,满足两个大条件即可构成重载:1.方法名相同 2.参数列表不同(参数个数,参数类型,参数顺序)
首先我们要明白那些类型是基本数据类型,哪些是引用数据类型
基本数据类型:short int long float double char boolean byte;
引用数据类型:数组 类 接口
提到数据类型传递就先介绍一下什么叫形参,什么叫实参;
在方法调用的时候,参数传递分为两种:
参数是基本数据类型时,传递的是值;如下图,int是基本数据类型,所以调用方法参数传递后,值并没有改变。
参数是引用数据类型时,传递的是地址;如下图:参数为数组引用类型,将arr传入后,然后method()方法修改了数组的第0个元素,然后打印发现原数组arr的第0个元素也发生了改变,所以从此可以看出,引用类型传递的是地址。
注:String在传递时有点特殊;虽然String是引用类型,但是传递的是值,而不是地址,所以原来的字符串str1的值并没有改变。
this始终指向本类对象
this可以调用本对象的所有属性以及成员方法
this可以调用本类的构造方法
this还可以返回当前对象的引用
注:当在一个类的一个方法里出现了同名变量,此时可以使用this,eg:this.name = name;
static修饰变量:又称静态变量,静态变量是所有对象所共享的,在内存中只有一个副本,只被初始化一次(在类加载的时候被初始化),而非静态变量则是在对象创建的时候才初始化,非静态变量的值是对象所拥有的,所以互不影响。访问时:类名.属性名
static修饰方法:又称静态方法,静态方法可以不依赖对象,而直接通过类名访问。一般用于定义工具类。
注:静态方法不能访问类的非静态成员变量和非静态成员方法,非静态方法可以访问静态方法和静态变量;
静态代码块:在类中,方法外,用static修饰,用于给类初始化;只执行一次!
构造初始化:在类中,方法外,用{}括起来,每次创建对象都会执行,用于给对象初始化。
局部代码块:在类中,方法内,用{}括起来,在局部位置,用于限定变量的生命周期。
package test02;
public class Test01 {
//静态代码块:类中方法外,加static修饰,用于给类进行初始化,只在类加载的时候执行一次
static{
System.out.println("静态代码块");
}
//构造代码块:类中方法外,用{}括起,每次调用构造方法前执行,用于给对象进行初始化
{
System.out.println("构造代码块");
}
//构造方法
public Test01(){
System.out.println("无参构造");
}
}
class test{
public static void main(String[] args) {
{
int a = 22;
System.out.println("a = " + a);//在局部代码块中打印输出a可以正常输出
System.out.println("局部代码块");
}
// System.out.println("a = " + a);//a在局部代码块外,所以在块外输出会报错,生命周期只块中
Test01 t2 = new Test01();
System.out.println("========================");
Test01 t3 = new Test01();
}
}
众所周知,提到java大家对包应该都不陌生吧,java中有很多各种各样功能的包,这使得我们在写代码时不需要什么事都需要自己写什么功能都需要自己来完成。我们只需要在用到什么功能的时候只需要导包即可。
java导包有两种方式:
1.单类型导入:import java.util.Scanner;
2.按需类型导入:import java.util.*;
第一种方式:只导入java.util包中的Scanner类,当你想用到这个包中的其他类就还需要在导入那个包,比如当此时你还需要用到Math类,此时你还需要导入java.util.Arrays;这个包,也就是你用到那个包就需要导入那个包。
第二种方式:import java.util.*;表示只要是java.util这个包下面的所有类的功能你都可以直接使用,而不需要在导包了。
注:有的小伙伴看到这儿,就想说了,既然这第二种方式这么好用,那我以后就都用第二种方式了。其实事实上第二种方式并不是那么完美。设想一个情景,此时我们导入的两个包比如import java.util.*;import java.io.*;假设这两个包里都有一个类名叫AAA的类,此时如果你是编译器你会知道你应该使用哪一个吗?所以由此可以看出,第二种方式也并不是完美无瑕。如果你去看一下java的源码你也会发现,里面的文件基本都是用到那个导入哪个,也就是用第一种方式导入。
如下图是String的源码的部分导包: