类与对象
面向对象的设计中更多情况下考虑的是标准的模块化设计,在使用时根据标准进行拼装。
面向过程是面对于一个问题的解决方案,更多情况下不会做出可重用的模块化设计。
面向对象是三个主要特征:
- 封装
内部的操作对外部而言不可见。当内部的操作都不可直接使用时,才是安全的; - 继承
在已经有的结构的基础上继续进行功能的扩充; - 多态
范围内可以变化的处理形式;
进行面向对象的程序开发中一般有三个步骤:
- OOA:面向对象分析
- OOD:面向对象设计
- OOP:面向对象编程
设计原则:生活中说得通的场景在程序中也可以说得通的。
类与对象:
类是对某一类事物的共性的抽象概念,对象描述的是一个具体的产物。
如:我和别人进行比较时,可以立刻区分。
所谓人和人的不同依靠的是各自的属性,每一个属性的集合构成了一个群体的定义,这个群体的定义就形成了类。
类是所有对象的共性产物,对象是一个个具有鲜明特征的具体的可以使用的产物。
类是一个模板,对象是类可以使用的实例。
类中有两个组成:成员属性和操作方法。
- 成员属性;
- 操作方法:定义对象具有的处理行为;
class 定义类。
使用类,通过对象来调用。如果产生对象,那么必须用如下格式来完成:
- 声明并实例化对象:类名称 对象名称 = new 类名称();
- 分步骤完成:
- 声明对象:类名称 对象名称 = null;
- 实例化对象:对象名称 = new 类名称();
使用对象操作类:
- 调用类中的属性:实例化对象.成员属性;
- 调用类中的方法:实例化对象.方法名称();
例子:
类本身属于引用数据类型,既然是引用数据类型,那么就牵扯到内存的引用传递,引用传递的本质:
同一块堆内存空间,可以被不同的栈内存所指向,也可以更换指向,
范例:定义一个引用传递的分析程序
String 类
所有字符串都要求"“进行定义,同时也利用”+"来进行字符串的连接。
String 类简介:字符串严格意义来讲,不能算是一个基本数据类型。Java里为了方便项目编写,利用其JVM的支持制造了一种可以简单使用的String类,并且可以像基本数据类型一样,进行直接的赋值处理。
(1) String 实例化
String类中之所以可以保存字符串,是其中定义了一个数组,也就是String里面字符串中的每一个字符的数据都是保存在了数组之中。
提示–观察String类的源代码实现;D:\Java\jdk-10\lib\src.zip;
JDK1.8版本:以前的String支持类:
1.9及以后的String支持类;
两者支持的数量首先不一样。
从JDK1.9开始,String类中的数组类型采用了byte类型(字节数组),在1.8的String中,String保存的是字符数组。
字符串就是对数组的一种特殊的包装应用,但是同时也应该清楚:既然包装的是数组,所以字符串中的内容肯定是无法改变的。
在String类里除了可以使用直接赋值的形式未对象进行实例化操作外,还可以按照传统方式,利用构造方法进行实例化的处理。
String本身包装的是一个数组,其有两种对象的实例化形式:直接赋值,和构造方法实例化。
字符串比较:
int型的变量相等,通过"=="来完成。但是String类实际上也牵扯到一个相等的判断问题,但是对于String类相等的判断,也可以使用=,但是不准确。
虽然字符串对象的内容是相同的,但是==无法得到准确的判断。这种情况下,如果想实现准确的字符串相等判断,可以使用String类所提供的一个比较方法equals:
如果以对象为例,每个对象中都有堆栈的引用。用new的话,两者不是指向同一内存空间,那么栈内保留的地址就不相同。
面试题:String比较重==与equals的区别。
- == 进行的是数值的比较,如果用于对象的比较,比较的是两个内存的地址数值的比较;
- equals是类提供的一个比较方法,直接对字符串的内容来进行比较。
字符串常量:
在程序的开发中,任何的整数都是int型,小数都是double。字符串不属于基本数据类型,任何使用的""定义的字符串常量表示的都是String类的匿名对象。
String stra = "mldn";
画成内存关系图该怎样画:
所谓的String类对象的直接复制直接描述的是,将一个匿名对象设置一个具体的引用名字。
为什么说字符串是匿名对象?
观察匿名对象的存在:
如果"mldn"是个匿名对象,那么其一定可以调用equals方法。(true)
此时可以发现:字符串常量可以明确调用equals()方法实现对象相等的判断,从而可以得出:程序中没有字符串的常量,有的只是String类的匿名对象。
整个对象在处理时,完全是系统来帮忙自动进行实例化的。
对象相等判断的小技巧:
- 以后进行项目开发时:如果现在某些数据是由用户输入,且要求这些数据为一个指定内容的情况下,建议将字符串常量写在前面。
用户可能不输入数据,没输入数据为空。
错误写法:
正确写法:将字符串常量写前面
equals方法可以自动回避空的判断,如果将字符串的常量写在前面,那么调用eauals()方法不会出现异常。
String类对象两种实例化方式比较:
两种处理模式使用哪种会更好。
- 直接赋值的对象实例化模式
只需要将字符串赋值给String类的对象,就可以实现对象的实例化处理。假设只有一行代码:
String str = "mldn";
只会开出一块堆内存空间。除了这种内存模式之外,利用直接赋值实例化String的形式,还可以实现同一个字符串数据的共享操作。
观察String直接赋值的数据共享: - 此时程序的结果返回的是true。这两个对象所指向的堆内存是同一个,这时的内存关系如图所示:
- 为什么可以共享呢?
主要的原因是:在java程序的底层,提供有一个专门的字符串池,字符串数组。既然是数组,数组的内容都是一个个具体的数据。
在堆内存中存有一个字符串池。当第一次把数据放进的时候,值开始都是为空。 - 当再有一个strB时,会首先去查找池,如果池中有数据,会引用池中的数据。如果没有,会放个新的。
- 在采用直接赋值的处理过程之中,对于字符串而言可以实现数据的自动保存,如果再有相同的数据产生时,可以减少对象的产生,以提升操作性能。
- 构造方法实例化
构造方法进行对象实例化,可以说是在进行对象定义时的常见做法。
此时对于本程序而言,可以通过内存关系图进行观察:
字符串是一个匿名对象,匿名对象只占据堆内存空间。
会产生两块堆内存空间,而后只会使用一块,由字符串所定义的匿名对象会成为垃圾空间。
更换一种形式又会怎样?
直接赋值的特点在于:可以自动将对象保存到对象池之中。
除了以上的特点外,在使用构造方法实现String类对象时,不会自动出现保存到字符串池的处理。
观察构造方法实例化对象时的池操作:
false。构造方法实例化的对象是自己专用的内存空间,在String类中也提供手工入池的处理情况。
public String intern()
在使用构造方法定义对象之后,由于使用了intern()方法,所以即便是构造出来的String类对象内容,也可以实现池管理,但太啰嗦。
面试题:解释String类两种对象实例化方式的区别?
- 直接赋值:只会产生一个实例化对象,并且自动保存到对象池之中,以实现该字符串实例的重用;
- 构造方法:会产生两个实例化对象,且不会自动入池,无法实现对象重用,但可以利用intern()方法手动的入池处理。
遇到String,用直接赋值的方法最稳妥。
String对象常量池:
对象池的主要目的是实现数据的共享处理,以String的对象池为例,里面的内容主要是为了重用。
对象池可分为两种:
- 静态常量池
指的是程序(.class)在加载时,会自动将此程序之中保存的字符串,普通的常量,类,和方法的信息全部进行分配; - 运行时常量池:当一个程序(*.class)加载后,里面可能有一些变量,这个时候提供的常量池;
观察一个程序:(静态常量池)
范例:观察一个程序–
答案是true。
本程序中所给出的内容都是静态常量数,字符串的常量都是匿名对象。所以最终程序加载后会帮助开发者处理好相应的连接。
一个是加载前,一个是加载后。三个常量相加,这样程序在进行处理时,会指向同样得内存空间。
运行时常量池范例:
答案是:false。之所以是false,是因为程序在加载时不确定info是什么内容。因为在进行字符串连接时,info是一个变量,变量得内容是可以修改的,故不认为最终的strB是一个所需要的最终结果。
变量数据即便输入内容一样,也有可能不等。运行时常量池和静态常量池两种。
字符串修改分析
String本质是一个数组,数组的最大缺点是长度不可改变,当设置了一个字符串之后,会自动的进行一个数组空间的开辟,开辟的内容长度是不固定的。
字符串的内容一旦定义,不能改变。观察一个程序:
分析下程序的内存处理操作:
String不可修改,栈内存的空间就是str,同时栈内存的内容是’www’。
String str = "www";
如果str +="mldn.";
字符串是匿名对象,匿名对象会产生新的空间。指向了新的堆内存空间,会断开一次连接。
充斥着垃圾空间,同时,对象总是在断开和连接过程中不断的进行切换。字符串的内容没有改变,改变的只是引用。
通过此时的程序可以发现,在整个处理过程中,字符串常量的内容并没有发生任何改变,改变的只是字符串的引用,且这种改变将有可能带来大量的垃圾空间。
String类在开发中不要对内容进行频繁修改:
主方法组成分析
public:描述的是一个访问权限,主方法是一切的开始点,开始点一定是公共的;
static:java程序的执行是通过类名称完成的,故表示此方法可以通过类直接调用;
void:主方法是一切的起点,起点一开始就没有返回的可能;
main:系统定义好的方法名称;
String args[]:字符串的数组,可以实现程序启动参数的接受;
例子:输出程序的启动参数。
在程序执行时可以设置参数,每一个参数之间进行一个空格分隔。
但是千万要记住,如果参数本身拥有空格,那么就需要使用双引号来包装。
使用这种启动参数实现数据输入的模拟。
String类常用方法
JavaDoc文档简介
只要是项目,就一定会存在String类定义,所以掌握这个类中常用处理方法,对开发者而言非常重要。
JavaDoc:
在以后进行开发过程中,大量使用Java的API文档,这个文档可以通过Oracale在线访问来查看。
知道的包越多,学的越明白。
如果现在要看String类的相关定义,可以打开java.lang这个包。
文档一般都会有翻译版,不要用翻译版。java开发文档没有中文,要习惯阅读英文文档。
字符串与字符数组
String利用了字符数组实现了包装处理,所有方法有构造方法和普通方法两类。
构造方法:
public String(char[] value) 将传入的全部字符数组变成字符串;
public String(char[] value,int offset, int count) 将部分字符数组变成字符串;
普通方法:
char charAt(int index): 获取指定位置的字符;
char[] toCharArray() 将字符串中的数据以字符数组的形式返回;
利用charAt()是可以获取某一个指定索引位置的字符,但是程序之中的索引下标都是从0开始的。在程序语言之中,最早一直强调的是字符串应该使用字符数组进行描述,所以这一操作在String类的方法中也是有所体现的。
范例:实现字符串与字符数组的转换
现在假设要做一个验证功能,判断某一个字符串中的数据是否全部由数字所组成。
- 最好做法是将字符串变为字符数组;
- 可以判断每一个字符是否在数字的范围之内;(‘0’~‘9’)
- 如果有一位不是数字则表示验证失败;
实际开发中,处理终问时使用char类型,因为其可以包含中文数据。
字符串与字节数组
当进行了字符串与字节转换时,其主要目的是为了进行二进制的数据传输,或者进行编码转换。
String String(byte[] bytes) 将全部的字节数组变为字符串;
String String(byte[] bytes, int offset, int length) 将全部的字节数组变为字符串;
public byte[] getBytes() 将字符串转为字节数组;
byte[] getBytes(String charsetName) 编码转换;
字符串比较
equals()方法,注意进行大小写区分。
除了equals之外,还有其他比较方法。
compareTo:会返回一个int数据,有三种取值:大于,小于,等于。
就是做大小比较的。
进行字符串的大小比较–
compareTo返回值要记住;
字符串查找
从一个完整的字符串中查找子字符串,一共有如下查找方法:
例:判断子字符串方法是否存在
但是在1.5之后才有的方法。在1.5之前,查询只能用indexOf的方法完成。
判断字符串是否存在–
indexOf是为了进行子字符串位置的查询,可以按照此形式进行索引位置的确定。
indexOf可以由前向后进行查找,也可以由后向前进行查找。
使用lastIndexOf来进行查找:
字符串查找也需要判断开头或结尾的操作,判断是否以指定的字符串开头或结尾:
字符串替换
通过一个指定内容来机械能指定字符串的替换显示。
字符串拆分
拆分操作根据指定的字符串或表达式实现字符串拆分,拆分完的数据以数组形式返回。
观察字符串的拆分处理:
除了全部拆分外,还可以拆分为指定个数。
拆分时有可能会遇到拆不了的情况,'192.168.2.3’以点拆拆不开。
使用双斜线"\"进行转义:
字符串截取
有时开始或结束索引往往是通过indexOf计算而来的。
观察截取:
取出张三。
字符串格式化
其他
isEmpty()主要是判断实例化内容,需要在有实例化对象时进行调用。
在进行数据输入的时候,难保证输入数据无空格,需要对输入的数据进行处理。
在String类中提供大小写转换,但是这种转换特征可以避免非字母的转换。
观察大小写的转换。缺少首字母大写方法。
自定义首字母大写方法: