面向对象基础
5.1:基本概念
概念区分 面向过程与面向对象(蛋炒饭和盖浇饭)
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了;面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为
面向对象三个主要特性
-
封装
-
把对象和属性看成一个密不可分的整体,两者"封装"在一个密不可分的单位(对象)中
-
信息隐蔽作用 把不需要外界知道的信息隐藏起来
-
-
继承
动物和人,人继承了动物
-
多态
方法重载和对象多态
5.2:类与对象
理解:类实际上是表示一个客观世界莫类群体的一些基本特征属性,对象是一个个具体的东西
比如
class Person{
private String name;
Private int age;
//其他省略
public static void main(String args[]){
Person person = new Person("张三",18);
}
}
Person是一个类,他表示人这个类有名字和年龄 person是一个对象,他是一个具体的人,这个人叫张三,年龄18岁
-
类使用前必须实例化
实例化之后就会在堆中分配内存,这样我们才可以使用对象的属性和方法,要不然我们无法使用,因为还未实例化的对象只是在栈中,如果实例化,栈里面储存的是对象在堆中的地址,没事实例化之前不指向任何地方.也就无法使用变量和方法
5.4:创建多个对象与对象引用传递
类属于引用数据类型,引用数据类型指一段堆内存可以同时被多个栈内存指向
Person per1 = new Person();
Person per1 = new Person();
Person per3 = new Person();
Person per4 = per3;
两者区别在于per1, per2创建了两个对象,分配了两个栈空间和两个堆空间 per3,per4创建了两个栈空间,这两个栈空间同时指向per3实例化时创建的堆空间
5.5封装
一个类中的属性如果不是私有的话,将属性和具体实现隐藏起来,对外界只提供接口
首先保护了属性,不会被外界直接调用,直接调用可能会引起位置错误,因为外界不知道这个属性的约束条件
其次提高代码的复用性
5.6:多态
-
构造方法
访问权限 类名(类型1 参数1,类型2 参数2,....){ }
构造方法声明
-
必须和类名一样
-
不能有返回类型声明
-
构造方法里不能使用return
-
访问权限默认是default 不是public private
类中没有声明构造方法时实际编译时会自动生成一个无参数构造方法,有了之后就不会自动生成
构造方法重载
5.7:匿名对象
-
匿名对象就是没有明确给出对象名字,一般匿名对象只使用一次,而且匿名对象只在堆里面开辟空间,而不存在栈内存的引用
public static main(String args[]){ new Person("张三",18).方法(); //匿名对象 }
5.8:String类
-
"==" 和equals()比较
==比较地址,equals()比较每一个字母
使用equals()技巧,防止报空指针异常
"hello".equals(str)
-
两种实例化方式比较
String str1 ="hello"; String str2 = new String("hello");
第一种开辟一片堆内存空间,并且会自动入池,第二在中会开辟两个堆内存空间,不会自动入池
-
对象池
jvm底层会存在一个对象池,不一定只保存String,使用直接赋值的方式时,回想该对象对做使用的匿名对象入池保存,后面如果有其他的String直接赋值时,如果内容相同,将不会开辟堆内存空间,而是使用已有的对象进行引用的分配,从而继续使用
-
字符串内容不可变
不要循环修改String内容
解决办法 :StringBuffer
5.9:this关键字
-
表示类中的属性
-
可以使用this调用本类的构造方法
-
this表示当前对象
//1.表示类中的属性 public class Demo2 { private int age; public Demo2(int age) { age = age; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public static void main(String[] args) { Demo2 demo2 = new Demo2(18); System.out.println(demo2.getAge()); //0 } }
当构造函数中没有使用this时,系统会默认使用最近的age,构造方法传入的参数age,构造函数中就是18 = 18,没有使用到属性
//2.可以使用this调用本类的构造方法 public class Demo2 { private int age; private String name; public Demo2() { System.out.println("无参数构造方法"); } public Demo2(int age, String name) { this(); this.age = age; this.name = name; System.out.println("有参数构造方法"); } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public static void main(String[] args) { Demo2 demo2 = new Demo2(18,"张三"); } }
5.10:static关键字
-
全局属性 用对象来改不合适 同时对象只能修改自己的
java常用内存区
-
栈内存:别处所有对象名称(跟准确的说是保存引用堆内存空间的地址)
-
堆内存:保存每个属性具体内容
-
全局数据区:保存static类型的属性
-
全局代码去:保存所有的方法定义
-
-
关于static方法定义说明
本类中没有提供普通属性,这样产生实例化没有意义
本来无法直接进行对象实例化,只能static操作
如果一个方法要由主方法调用,那么这个方法必须是static,因为主方法是静态方法,静态方法不能调用非静态方法
-
构造块和静态代码块
构造块在构造方法之前执行,每次实例化对象都会执行
静态代码块优于主方法执行,只执行一次
-
构造方法私有化
public class Demo3 {
static Demo3 demo = new Demo3();
private Demo3(){
}
public void print(){
System.out.println("Hello World");
}
}
class Demo3Test{
public static void main(String[] args) {
Demo3 demo3 = null;
demo3 = Demo3.demo;
demo3.print();
}
}
首先将构造函数私有,外界将无法实例化对象,那么只能在类中实例化,将实例化对象用static修饰,直接用类名调用,就实现了构造函数私有化
意义,永远只有一个Demo3实例,单例模式https://www.runoob.com/design-pattern/singleton-pattern.html
5.11:内部类
-
可以方便的访问外部类的私有属性
-
使用static定义内部类
public class OuterClass { private static String info = "Hello World"; static class inner{ public void print(){ System.out.println(info); } } } class OuterClassTest{ public static void main(String[] args) { new OuterClass.inner().print(); //访问方法 } }
-
在外部访问内部类
public class OuterClass { private static String info = "Hello World"; class inner{ public void print(){ System.out.println(info); } } } class OuterClassTest{ public static void main(String[] args) { OuterClass outer = new OuterClass(); OuterClass.inner inner = outer.new inner(); //外部类.内部类 内部类对象 = 外部类实例.new 内部类(); } }
-
方法中定义内部类
public class FunctionClass { private String info = "Hello World"; public void fun(int temp){ class inner{ public void print(){ System.out.println("类中的属性"+ info); System.out.println("方法中的属性"+temp); } } new inner().print(); } }
class FunctionClassTest{ public static void main(String[] args) { new FunctionClass().fun(30); } }
方法中的类可以访问到方法中的属性!!!