目录
1.面向对象程序设计概述
面向对象程序设计(简称OOP)是当今主流的程序设计范型,它取代了20世纪70年代的“结构化”过程化程序设计开发技术。C语言是面向过程的编程语言,而Java/C++是面向对象的编程语言(对象 + 行为 + 对象),就是一个对象发出,然后作用于另外一个对象或某些对象。
面向对象的程序是由对象组成的,每个对象包含对用户公开的特定功能部分和隐藏的实现部分。程序中的很多对象来自标准库,还有一些是自定义的。只要对象能够满足要求,就不必关心其功能的具体实现过程。
面向过程:1.把冰箱打开2.把大象放入3.把冰箱关起来。
面向对象:打开冰箱,储存,关闭都是对冰箱的操作,是冰箱的行为。冰箱就是一个对象,所以只要操作冰箱所具有的功能,都要定义在冰箱中。
面向对象的概念:1.面向对线是思考问题的一种思考方式,是一种思想。
2.类就是一类对象的统称,对象就是这一类的具体化的一个实例。
3.面向对象的好处:将复杂的事情变简单了,只要面对一个对象就行。
面向对象设计:面向对象设计把握一个重要的经验:谁拥有数据,谁对外提供操作这些数据的方法!(被动的一方是数据的拥有者,主动的一方是执行者)。开发时:找对象,建对象,用对象,并维护对象之间的关系。
简而言之:面向对象就是用代码来描述客观世界的事物的一种方式,一个类主要包含一个事物的属性和行为。
2.类和类的实例化
2.1类
类:抽象概念,无法具体到某个实体。类是描述某一些对象的统称,对象是这个类的一个实例而已,这一类对象所具备的共同属性和行为(方法)都在类中定义。总的来说,类就是一个模板,对象就是由模板产生的样本,一个类,可以产生无数的对象。
声明一个类,就是创建一个新的数据类型,而类在Java语言中属于引用数据类型,Java使用class来声明类。类的命名使用有意义的大驼峰命名法,class不需要首字母大写。类中定义的成员都有默认值(默认值就是这个变量所在类型的默认值):String 默认值null;int 默认值 0。
成员变量可以在定义时赋值,成员变量就地初始化。
public class Text {
public static void main(String[] args) {
Person per1 = new Person();
per1.name = "张三";
per1.age = 18;
per1.sex = "男";
per1.print();
Person per2 = new Person();
per2.print();
}
}
class Person{
String name;
int age;
String sex;
void print(){
System.out.println("姓名:"+name+",年龄:"+age+",性别:"+sex);
}
}
//运行结果
姓名:张三,年龄:18,性别:男
姓名:null,年龄:0,性别:null
类名称Person中name和sex的默认值为null,age的默认值为0。假设per1的首地址为0x1,per2的首地址为0x2,就相当于拿着per1的引用访问了堆内存的地址,然后把name,age,sex给改了,而per2则没有此操作,输出默认值。
若再执行per1 = per2 ,per1本来保存的地址为0x1,现在保存的地址为0x2。
执行此操作:
System.out.println(per2.name.length());
null在Java中为“空引用”,只有名字没有保存任何堆内的地址,表示不引用任何对象,类似于C语言中的空指针。如果对null进行.操作就会引发异常。
封装(有时称为数据隐藏)是与对象有关的一个重要概念。从形式上看,封装不过是将数据和行为组合在一个包中,并对对象的使用者隐藏了数据方式。对象中的数据称为实例域,操纵数据的过程称为方法。实现封装的关键在于绝对不能让类中的方法直接地访问其他类的实例域。程序仅通过对象的方法与对象数据进行交互。
创建类的语法
class 类名称{
//属性(实例属性,成员属性)
//行为(实例方法,成员方法)
}
在Java中一个源文件中,只有一个主类(public class 类名称)。
public class Text {
public static void main(String[] args) {
Person person = new Person();//通过new实例化一个对象
person.eat();//成员方法的调用需要通过对象的引用调用
person.sleep();
// 产生对象 实例化对象
Person person2 = new Person();
Person person3 = new Person();
}
}
class Person{
void eat() {//成员方法
System.out.println("吃饭!");
}
void sleep() {
System.out.println("睡觉!");
}
}
//运行结果
吃饭!
睡觉!
注: new关键字用于创建一个对象的实例
使用" . "来访问对象中的属性和方法
同一个类可以创建多个实例
2.2类的实例化(对象)
同一个类的所有对象实例,由于支持相同的行为而具有家族式的相似性。对象的行为是可调用的方法定义的。
此外,每个对象都保存着描述当前特征的信息。这就是对象的状态,对象的状态可能会随着时间发生改变,但这种改变不是自发的。对象状态的改变必须通过调用方法实现。(如果不经过方法的调用就可以改变对象状态,只能说明封装遭到了破坏。)
但是,对象的状态并不能完全描述一个对象,每个对象都有唯一身份。作为一个类的实例,每个对象的标识永远是不同的,状态常常也存在着差异,对象的这些关键特性在彼此之间相互影响着。
类名称 引用名称 = new 类名称();
Person per = new Person();
看见new就有新空间,而且是堆上的新空间。new Person()就是对象,在堆中存储。per称为对象的引用,实际上就是给这个对象起一个名字。
3.static关键字
3.1 static的含义和用法
修饰属性(类属性,类变量):Java静态属性和类相关,和具体的实例(对象)无关。换句话说,同一个类的不同实例公用同一个静态属性。所有共享类,且不属于对象,直接通过类名称就可以访问,无需通过对象。访问方式为:类名.属性。
当一个实例变量被static修饰以后,他就表示类的一个属性,该类的所有对象都共享这个属性,所有对象的属性值都一样,static修饰的属性在JVM方法区中存储,所有该类对象共享属性。
修饰方法(类方法,工具方法):如果在任何方法上应用static关键字,此方法称为静态方法。
1.静态方法属于类,不属于类的对象。
2.可以直接调用静态方法,而无需创建类的实例。
3.静态方法可以访问静态数据成员,并可以更改静态数据成员的值。
为什么主方法是个静态方法?
主方法是一个程序的入口,如果方法是个成员变量,就要通过对象调用。入口都没有,怎么产生对象。
程序从主方法开始执行,主方法要能调用起来,静态方法,直接调用,无需产生对象。
静态方法能否访问成员变量和成员方法?(不能 )静态方法没有该类对象就能访问。
成员方法能否访问静态变量和静态方法?(可以)成员方法和成员变量,产生该类的对象才能访问。
结论:1.静态方法中只能调用静态方法或者静态属性,static家族之间可以相互调用。不能直接调用成员方法和成员属性,必须通过对象来调用。
2.在成员方法中既可以调用成员方法,也可以调用静态方法(此时都已经产生了该类的对象,一定可以访问静态域)
共享的变量属性,设计为静态变量
工具类的方法设计为static方法,例如Arrays.toString()
修饰代码块(静态代码块)
修饰内部类(静态内部类)
public class Lei {
public static void main(String[] args) {
Person per1 = new Person();
per1.name = "张三";
per1.sex = "男";
per1.age = 18;
Person.country = "中国";
// country被赋值为“中国”
// country这个成员变量,使用类名称直接访问。
Person per2 = new Person();
Person.country = "大中国";
// country被赋值为“大中国”
//调用print方法,使用变量名.方法名调用此方法。
//由于程序运行是从上至下的,static关键字同一个类的不同属性公用同一个静态属性
//故country的属性值为“大中国”,而非“日本”和“中国”。
per1.print();
per2 .print();
}
}
class Person{
String name;
String sex;
int age;
static String country = "日本";
//static关键字修饰country,赋值了“日本”。
void print(){//成员方法
System.out.println("name ="+name+",age ="+age+",sex ="+sex+",country ="+country);
}
}
//运行结果
name =张三,age =18,sex =男,country =大中国
name =null,age =0,sex =null,country =大中国
static修饰的属性在JVM方法区中储存,所有该类对象共享此属性。
调用new Person()来产生Person的对象,先要有Person类才能产生对象。首先将Person类加载到内存中,Person中的所有static变量就会被加载到方法区中。方法区一开始就有Person.country = "中国" ,堆中就有name = null,age = 0,sex = null。(成员变量在堆中存储;static修饰的变量在方法区中存储)
static修饰的属性,直接通过类名称就可以访问,无需通过对象访问。(Person.country)
在Java中能否在方法的内部定义一个static变量?
答案是不能滴!方法中定义的全是局本变量,局部变量都在栈中存储,而static变量是在JVM的方法区中存储。不可能定义一个既在栈中又在方法区中存储的变量。
3.2final和static的区别
若在类中定义一个常量,一般都会使用全局常量,static final共同修饰,必须在定义时赋值,称为类的常量。常量的命名规则:所有单词全部大写,多个单词使用下划线分隔,static final String STUDENT_SCHOOL="清华大学"(节省空间)要使用类属性,我们通常直接通过类名称.属性名称,不推荐使用对象来调用属性。
Person per = null;
System.out.println(Person.country);
System.out.println(per.country);
static属性称为类属性,通过名称直接访问,此时没有对象也能调用(包含该类的null引用)。
4.封装(保护和易用)
面向对象一共有三大特性:封装,继承和多态。
封装有很多表现形式,private实现属性和方法的封装只是封装的一种。
在Java中,所谓的权限修饰符,指的是你修饰符的属性,方法,类,到底可见的范围有多大。
一共有四大修饰符,可见范围依次从小到大为:private,default(不要写这个关键字,啥权限也没有就是default),protected,public。
被private修饰的属性和方法,只在类的内部可见,出了类{},对外部就完全隐藏了,外部不知道其存在。
private可以修饰一个类吗?(类的定义就是产生对象,供外部使用,private定义完对外部隐藏,无法修饰。)
被public修饰的东西,在当前程序(项目)中是可见的。
想在类的外部访问这些私有属性,需要使用类提供的getter(取值)setter(修改值)
哪些需要提供getter(get.属性名称 = 方法命名),让外部可见;哪些属性要提供setter(set.属性名称 = 方法命名),让外部修改,都要根据这个属性的特征来决定。
快捷键:alt + insert
保护性:要是没有封装,有些东西就直接 通过对象直接访问了。例如:银行卡密码。
易用性:在方法的内部,把一些属性来进行调配和操作,对于用户来说这些属性是不可见也不关注的。
所有引用类型的对象比较使用equals方法。
类中的构造方法:类中非常特殊的一种方法,使用关键字new实例化对象实际上就调用了该类的构造方法。构造方法的作用就是产生对象。
使用关键字new产生一个对象时,大致分为一下两步:
1.为对象在对中分配新空间 2.调用对象的构造方法对成员变量赋值(成员变量的默认值都在构造方法中赋值的,当构造方法调用结束,该对象就初始化完成。)
构造方法的语法规则:
1.方法的名称和类名称完全一样。
2.构造方法没有返回值声明(不是void)
3.一个类中至少存在一个构造方法,若没有显示定义,编译器会产生一个默认的无参构造。(当类中自定义了构造方法,则默认的无参构造就不在生成)
public class Lian {
public static void main(String[] args) {
Person per = new Person();
}
}
class Person{
private String name;
private int age;
public Person(){
System.out.println("Person构造方法");
}
}
//运行结果
Person构造方法
当我们在new一个新的对象时,就默认调用这个对象的构造方法,如果一个类中没有定义构造方法,编译之后,编译器就会生成一个默认的无参构造。当类中自定义了构造方法,默认的无参构造就不再生成了。
构造方法的重载:此时的重载只可能是参数的个数不同,成员变量在初始化时数据类型已经确定了。
public class Lian {
public static void main(String[] args) {
Person per = new Person();
Person per1 = new Person("jack");
Person per2 = new Person("jack",18);
}
}
class Person{
private String name;
private int age;
public Person(){
System.out.println("Person的无参构造");
}
public Person(String n){
name = n;
System.out.println("name ="+ name);
System.out.println("Person有参构造");
}
public Person(String n,int a){
name = n;
age = a;
System.out.println("name =" + name +",age =" + age);
System.out.println("Person的两个有参构造");
}
}
//运行结果
Person的无参构造
name =jack
Person有参构造
name =jack,age =18
Person的两个有参构造
由输出结果可以看出,new的对象按顺序调用Person的构造方法。
5.this关键字
修饰调用当前对象的成员变量,调用当前对象的方法(普通方法和构造方法的相互调用),表示当前对象的引用(当前的属性或者方法是哪个对象调用的,this就指代这个对象)。
public class ThisText {
public static void main(String[] args) {
Student stu = new Student("jack","男",18);
stu.show();
}
}
class Student{
private String name;
private String sex;
private int age;
public Student(String name,String sex,int age){
//形参的名称与成员变脸一致。//
// 这样写就等同于形参自己等于了自己,对成员变量没有影响。
name = name;
sex = sex;
age = age;
System.out.println("Student的有参构造");
}
public void show(){
System.out.println("name="+name+",sex="+sex+",age="+age);
}
}
//运行结果
Student的有参构造
name=null,sex=null,age=0
如何打破编译器的就近原则:使用this关键字(this.成员变量名称)调用它的成员属性。
this.name = name;
this.sex = sex;
this.age = age;
加上this.后的运行结果:
Student的有参构造
name=jack,sex=男,age=18
就表示name,age,sex就是成员变量的名称,所以就修改了成员变量。
public class ThisText {
public static void main(String[] args) {
Student stu = new Student();
stu.fun();
}
}
class Student{
private String name;
private String sex;
private int age;
public void text(){
System.out.println("Student类的text的成员方法");
}
public void fun(){
text();
System.out.println("Student类的fun的成员方法");
}
}
//运行结果
Student类的text的成员方法
Student类的fun的成员方法
fun方法在内部调用了text成员方法,在这里编译器帮你在text之前加上this.所以写和不写this.不影响。
public class ThisText {
public static void main(String[] args) {
Student stu = new Student();
Student stu1 = new Student("jack");
Student stu2 = new Student("jack",18);
}
}
class Student{
private String name;
private String sex;
private int age;
public Student(){
System.out.println("---------");
}
public Student(String name){
System.out.println("---------");
this.name =name;
}
public Student(String name,int age){
System.out.println("---------");
this.name = name;
this.age = age;
}
}
//运行结果
---------
---------
---------
若把第二个有参构造方法中的System.out.println("---------");改为this.();
若把第三个有参构造方法中的System.out.println("---------");改为this(name);
运行结果一样,若不同参数的构造方法之间出现了重复的调用,可以使用this(参数)表示调用其他的构造方法。
this规则:this调用其他构造方法必须放在构造方法的首行,this调用构造方法不能成“环”。
6.代码块
代码块:根据定义的代码块的位置以及关键字的不同分为以下四种代码块:
普通代码块(定义在方法中,防止重名),成员代码块(直接定义在类中,不加任何修饰符的代码块,优先于构造方法执行,有几个对象产生就调用几次构造块,使用{}括起来的代码块,也叫构造块。),静态代码块(定义在类中,使用static修饰的代码块,在类加载的过程中只加载一次,与对象无关。),同步代码块。 概念:就是{}中的代码
主类的静态代码块优先于主方法执行,jvm要执行主方法,首先得加载主类,主类一加载,静态代码块就执行了。
静态变量存在于方法区中,类定义的时候就会有初始值,这个类就被放入方法区中,这个类只是定义了,还没有加载。
匿名对象:new出来的对象没有引用指向,使用一次后就销毁,不能在次使用。常用语测试类中的某些功能,使用一次后,就会被jvm销毁。程序语法:new Person();
toString方法:当一个引用类型的变量,调用println函数打印时,默认输出的都是引用类型的地址(不是真正的内存地址,Java程序员不知道确切的内存地址。)
7.每日一汤
没有人可以决定你做什么,你自己要很清楚,自己做了,错了,我不后悔。没有办法控制的事情太多了,所以唯一能控制的是自己,让自己的自律性更强,每天坚持锻炼哪怕20分钟,5公里,3公里,这样会使你更自信。人生要有更高的追求,而这种追求不是说,以后工资、职位比别人高什么的,而是为了自己心中的理想去奋斗,当然你有可能会败给现实,但是这样做使你每天过的充实。所以敲了一天代码的“宝子们”去锻炼一下吧!而我跟我的ID一样“@在等我打两行 ”就去。