基础篇_01的主要内容
- 1、 面向对象的基本概念
- 2、 类与对象的关系、引用传递
- 3、 类封装性的操作
- 4、 构造方法的定义及使用
- 5、 匿名对象(重点)
- 6、 String 类的使用
- 7、 this 关键字的作用
一丶面向对象的简单了解
面向对象是针对于一类问题来进行解决,某一局部的修改不影响其他位置的变化。
在面向对象中主要分为以下三个方面:
OOA:面向对象分析。
OOD:面向对象设计,根据分析的结果使用工具完成设计。
OOP:完成具体的功能实现,代码编写。
在面向对象中,实际上还存在着三个主要的特性:
封装性:private属性+public方法。
继承性:子类和父类之间的继承,方法的重写+属性的改变;
多态性:有继承+重写+父类引用指向子类对象
可以参考:
java面向对象的三大特性
二丶类与对象的关系
类是对象的模板,对象是类的实例
类:类是一组共性的产物,是同一类事物的集中表现。
对象:是一种个性的体现,是个体的产物。
对象中的所有操作行为都由类决定,所以,在使用中只要是类定义出的操作对象都可以应用,而如果类没有定义出的操作,对象肯定无法使用。
1丶类和对象
①在 Java 中可以使用 class 关键字来定义一个类,在类中有两大组成部分:属性(变量)、方法。
一个类定义完成之后肯定无法直接使用,需要依靠对象进行操作,这就是对象的实例化。
- 类名称 对象名称 = new 类名称() ;
一旦将对象实例化之后呢,可以通过“对象名称.属性()”和“对象名称.方法()”进行类的调用。
举例:
class Person{ // 定义类
String name ; // 表示一个人的姓名
int age ; // 表示一个人的年龄
public void tell(){ // 表示一个功能,说话
System.out.println("姓名:" + name + ",年龄:" + age) ;
}
};
public class Demo01{
public static void main(String args[]){
Person per = new Person() ; // 产生对象
per.name = "张三" ; // 设置 name 属性的内容
per.age = 30 ; // 设置 age 属性的内容
per.tell() ; // 调用方法输出
}
};
对象产生:Person per = new Person() ;
既然存在了关键字 new,而且类又属于引用数据类型,那么肯定现在
就开辟了相应的栈及堆内存空间,而且以上的代码可以拆分成两步:
|- 声明对象:Person per = null ; --> 在栈内存中声明
|-实例化对象:per = new Person() ; --> 开辟对应的堆内存空间
|-1、栈内存是存储变量的名称的。per作为变量名称存储在栈内存中。
|-2、new 了一个类名称之后,开始在堆内存中为这个类分配内存空间。
|-3、声明对象后的per就好比一个空的指针,在实例化对象之后,per指向了堆内存中person类中的属性,可以通过per.name="houzi"和per.age="3"对属性进行赋值,还可以通过per.tell();调用方法。
需要注意的是:
**※ 每一个对象拥有各自的内存空间,不会互相影响。
**※ 每一个对象中实际上保存的只是属性,并没有保存方法,因为所有的方法都是每个对象所共同拥有的,保存在 全局代码区 之中。
**※ 栈内存保存的是对堆内存的引用地址,栈内存-->堆内存,而堆内存中保存的是每一个对象所拥有的属性,而 全局代码区 之中保存的是所有类中的方法,表示公共调用。
2丶引用传递
+++引用到了上述的代码+++
引用传递指的就是一个堆内存空间,可以同时被多个栈内存所指向
**简单理解:就是在声明对象的时候,在栈内存声明了两个对象名称,并且同时指向了同一个实例化对象
实例化的对象在堆内存中开辟的空间是一个
声明两个对象,栈内存中的两个空间存放
本人理解为存放的是指针,只具有指向作用
Person per1 = null ;
Person per2 = null ;
这里两个对象的 指针 指向同一个堆内存中开辟的Person空间
per1 = new Person();
per2 = new Person();
举例:
public class Demo02 {
public static void main(String args[]){
Person per1 = null ;
per1 = new Person() ; // 实例化
Person per2 = null ;
per2 = new Person() ; // 实例化
//赋值操作
per1.name = "张三" ;
per1.age = 30 ;
per2.name = "李四" ;
per2.age = 20 ;
/*
*per2指向了per1的堆内存中保存per1访问属性的空间,
*造成per2原有数据丢失,访问的是与per1相同的属性。
*/
per2 = per1 ;
per2.tell() ;
}
};
三丶类封装性的操作
封装性就是指类内部的定义对外部不可见。
属性或方法不希望被外部用 所访问的话,则可以使用 private 关键字声明。
1丶在 JAVA开发的标准规定中,只要是属性封装,则设置取得就要依靠setter[进行内容的设置] 及 getter[取得] 方法完成操作。
【代码编辑界面右击】-->【source】-->【generate getter and setter】
<->只要是属性就必须进行封装,封装之后的属性必须通过setter和getter设置和取得。<->
<-->强调:在一个类中所有的方法是允许互相调用的,如果非要强调是本类中的方法的话,则在调用的方法前增加一个“this”关键字,表示的是本类中的方法。<-->
四丶构造方法的定义及使用
Person per = new Person() ;
Person()就表示的是一个构造方法,此构造方法属于默认的构造方法。
构造方法的定义:在一个类中定义的方法名称与类名称相同,且无返回值声明的方法。
在一个类中如果没有明确的定义一个构造方法的话,则会自动生成一个无参的,空的构造方法。
一个类永远都会保存至少有一个构造方法。构造方法可以重载。
方法重载:方法名称相同,参数的类型或个数不同。*
所有的构造方法是在对象使用关键字 new 进行实例化的时候调用的,而且每次使用关键字 new 开辟新的堆内存空间时,构造方法都要被调用。实际上构造方法的主要作用就是为一个类中的属性 初始化 的。
五丶匿名对象(重点)
匿名对象就是表示没有名字的对象。
匿名对象没有对应的栈内存所指向,所以使用一次之后就等待被垃圾回收了。
class Person{ // 定义类
private String name ; // 表示一个人的姓名
private int age ; // 表示一个人的年龄
public Person(String n,int a){// 通过构造方法为属性自动初始化
this.setName(n) ;
this.setAge(a) ;
}
public void setName(String n){ // 设置姓名
name = n ;
}
public void setAge(int a){ // 设置年龄
if(a>=0 && a<=150){ // 合法年龄
age = a ;
}
}
public String getName(){ // 取得姓名
return name ;
}
public int getAge(){ // 取得年龄
return age ;
}
public void tell(){ // 表示一个功能,说话
System.out.println("姓名:" + this.getName() + ",年龄:" + this.getAge()) ;
}
};
public class Demo03 {
public static void main(String args[]){
new Person("张三",30).tell() ;
}
};
通过设置一个含参数的构造方法,进行匿名对象的调用。
匿名与非匿名的差别:
在内存中的分布不同:匿名对象创建的对象只存在于堆中;非匿名对象创建对象时的对象虽然也在堆中,但其类变量却在栈中,栈中的类变量通过创建变量的内存地址来指向相应的对象。
从调用意义来看
- ①匿名对象调用方法有意义,而调用类中的属性则没有意义。例如:
new Student().name="wangwu";
–这属于使用匿名对象调用属性。这种调用没有意义,当代码执行到这一行代码时则修改new Student()对象的name属性,可是当该条语句被执行后呢?由于这时new Student()没有继续引用,所以此对象在堆中就成了垃圾。
–匿名对象调用方法有意义,方法存在于栈空间,当在内存中创建的对象调用方法时,JVM开始为局部变量开辟内存空间,方法开始执行,方法强调其功能,对象调用方法可以完成其功能,所以匿名对象调用方法有意义。
- ②非匿名对象调用方法或调用类中的属性都有意义(其中前者不在累述,请参见第①点)。例如:
Student stu=new Student();
stu.name=”wangwu”
-这属于使用非匿名对象调用属性。当代码执行到这一行代码时则修改stu对象的那么属性,此时使用该对象调用print()方法则输出的name值为wangwu,鉴于这一点所以认为非匿名对象调用属性实用意义的。
- ①匿名对象调用方法有意义,而调用类中的属性则没有意义。例如:
六丶String 类的使用
1、String 类的对象实例化
String 在使用中有两种实例化的方法。
一种是采用直接赋值(将字符串赋 String 的对象)
- String str = “Hello” ;
第二种方法是通过构造方法完成实例化的操作
- String str = new String(“Hello”) ;
2、字 符串 的 比较 ( 重 点)
“==” 用在数值上表示判断是否相等 ,如果是用在了对象上,则表示的是判断两个对象的地址是否相等。
- str1==str2
equals():用于内容的比较,比较两个字符串的内容是否相等
- str1.equals(str2))
3、一个字 符串个 就是一个 String 的 的 匿 名对象
一个字符串就是 String 类的匿名对象可以直接使用。
通过一个例子证明
public class Demo04 {
public static void main(String args[]){
System.out.println("hello".equals("hello")) ; // true
}
};
通过Demo04程序可以清楚的验证,之前使用直接赋值的方式为 String 类进行实例化的操作,就属于将一个匿名对象起了一个名字。
4、两种实例化的比较
String str = "TheString";
这样写的代码,只在堆内存中开辟了一块空间。
String str = new String("Hello") ;
- 由于内部的字符串属于匿名对象,字符”Hello”在堆内存中会有占有一个空间的位置,实例化new的时候会重新开辟一个空间来存放字符”Hello”,原有的字符串Hello的空间将变为垃圾。
- JAVA底层中存在了一个字符串的对象池,每次的内容都会从池中取出,如果内容已经存在了,则使用已经存在的,如果不存在,则会生成一个新的,放入池中,属于 共享设计模式。
5、字符串的内容一旦声明则不可改变
public class StringDemo {
public static void main(String args[]){
String str = "hello" ;
str = str + " world" ;
str += " !!!" ;
System.out.println(str) ;
}
};
每一个字符串的内容原本并没有发生任何的改变,改变的是只一个字符串的内存地址的指向,而且操作完成之后会发现有很多的垃圾产生。
6、String 类的相关操作( 类的相关操作( 重点)
在实际的开发中,String 类的使用是最频繁的,而且在 String 类中提供了大量的操作方法。
①字符串与字符数组
字符串和字符数组的转换
取出指定位置的字符
public class StringDemo01 {
public static void main(String args[]){
String str = "helloworld" ;
System.out.println(str.charAt(0)) ;//取出第一个字符
System.out.println(str.charAt(3)) ;//取出第三个字符
System.out.println("字符串的长度是:" + str.length()) ;//获得字符数组长度
char c[] = str.toCharArray() ; // 将字符串变为字符数组
for(int x=0;x<c.length;x++){//c.length是字符数组的长度
System.out.print(c[x] + "、") ;
}
System.out.println("\n" + new String(c)) ;
//把字符数组c变为字符串。
System.out.println(new String(c,0,5)) ;//把指定位置的字符数组变为字符串
}
};
②字符串与字节数组
一般在以后进行 IO 操作的时候往往会使用到字节数组的功能
将字符串变为字节数组
将指定范围的字节数组变为字符串
public class StringDemo02{
public static void main(String args[]){
String str = "helloworld" ;
byte b[] = str.getBytes() ; // 将字符串变为字节数组
System.out.println(new String(b)) ;
System.out.println(new String(b,0,5)) ;
//将指定范围的字节数组变为字符串
}
};
③字符串的比较、截取、存在、拆分、替换及其他操作
比较
- equals("HELLO") 考虑大小写的比较
- equalsIgnoreCase(String anotherString)忽略大小写的比较
public class StringDemo03 {
public static void main(String args[]){
String str = "hello" ;
System.out.println(str.equals("HELLO")) ;
//区分大小写的比较
System.out.println(str.equalsIgnoreCase("HELLO")) ;//忽略大小写的比较
}
};
截取
- substring(int beginIndex)从指定位置截取到末尾
- substring(int beginIndex,int endIndex)截取指定范围的内容
public class StringDemo04 {
public static void main(String args[]){
String str = "helloworld" ;
System.out.println(str.substring(5)) ;
//从第六个字符开始截取到最后
System.out.println(str.substring(0,5)) ;
//从一开始截取到第六个字符
}
};
存在
- indexOf(String str)从头开始判断,如果找到则返回位置的数值,找不到返回值-1
- indexOf(String str,int fromIndex)从指定位置开始查找,如果找到则返回位置,找不到返回-1
- contains(String s)直接判断是否存在
一般而言已经开发施加较长的人员都会使用 indexOf()进行判断,通过判断其是否是-1,来决定是否有内容。
public class StringDemo05 {
public static void main(String args[]){
String str = "helloworld" ;
if(str.indexOf("hello") != -1){
System.out.println("已经查找到了内容,位置是:" + str.indexOf("hello")) ;
}
}
};
拆分
-split(String regex)按照指定字符串拆分
在进行字符串拆分的时候,如果发现有某些字符串无法拆分,则使用转义字符"/"。
public class StringDemo06 {
public static void main(String args[]){
String str = "hello world !!!" ;
String s[] = str.split(" ") ;
//这里表示遇到空格变拆分字符串
for(int x=0;x<s.length;x++){
System.out.print(s[x] + "、") ;
}
}
};
替换
-replaceAll(String regex,String replacement)全部替换。
-replaceFirst(String regex,String replacement)替换第一个满足的内容。
public class StringDemo07 {
public static void main(String args[]){
String str = "helloworld" ;
System.out.println(str.replaceAll("l","⊙")) ;
System.out.println(str.replaceFirst("l","⊙")) ;
}
};
其他操作
public String toLowerCase()转小写。
public String toUpperCase()转大写。
public String trim()去掉左右空格。
public boolean startsWith(String prefix)判断是否以指定的字符串开头。
public boolean endsWith(String suffix)判断是否以指定的字符串结尾。
public class StringDemo08 {
public static void main(String args[]){
String str = " helloworld ".trim() ;
//去掉左右空格。
System.out.println(str) ;
System.out.println(str.toUpperCase()) ;
//转大写。
System.out.println(str.startsWith("hello")) ;
//判断是否以指定的字符串开头。
System.out.println(str.endsWith("d")) ;
//判断是否以指定的字符串结尾。`
}
};
7、对象数组:就是一组对象
类名称 对象数组名称 [] = new 类名称[对象数组长度] ;
类是引用数据类型,所以对象数组中的每一个内容都是 null,在使用的时候肯定是需要进行分别实例化的。
Person per[] = {new Person("张三",10),
new Person("李四",20),new Person("王五",30)} ;
Person per[] = new Person[3] ; // 开辟三个大小的对象数组
per[0] = new Person("张三",10) ;
per[1] = new Person("李四",20) ;
per[2] = new Person("王五",30) ;
七丶this关键字
访问属性
调用方法(包含了构造)
表示当前对象
1) this 关键字是类内部当中对自己的一个引用,可以方便类中方法访问自己的属性;
2)可以返回对象的自己这个类的引用,同时还可以在一个构造函数当中调用另一个构造函数。
1、访问属性
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
把构造方法中的 name 或 age 参数给类中的 name 和 age 属性的话,就需要通过 this 来表示出本类的属性。
this.name 是访问本类中的属性。后边的name是含参数构造器中的参数。
2、调用方法
|- 如果使用 this 调用本类中其他构造方法的话,则此语句必须放在构造方法的首行。
|-
一个类中如果有多个构造方法的话,则肯定保留有一个是不用this ” 调用其他构造的情况,以作为出口
|- 将参数少的构造方法放在最前面,参数多的构造方法放在最后面。
this() ; // 调用本类中的无参构造
this(name) ; // 调用有一个参数的构造
3、表示当前
通常在set方法和构造函数中都会使用, 当局部变量和成员变量同名时访问成员变量(因为成员变量会被局部变量覆盖)