封装
封装:是面向对象的核心思想,将对象的属性和行为封装起来,不需要让外界知道具体实现细节,这就是封装的思想。例如,我们使用电脑,只需要在键盘上输入,不需要知道电脑内部是如何工作
1. Java中的类与对象
1.1 关系
面向对象的思想中提出了两个概念 —— 类和对象。类:是对某一类事物的抽象描述,对象:用于表示现实中该类事物的个体
1.2 类的定义
类是对象的抽象,它用于描述一组对象的共同特征和行为。以面向对象的编程思想,就可以将某一类中共同的特征和行为封装起来,把共同特征作为类的属性(也叫成员变量),把共同行为作为类的方法(也叫成员方法)。
/*
1. Java中的类通过 class 关键字来定义
[修饰符] class 类名 [extends 父类名] [implements 接口名] {
//类体,包括类的成员变量和成员方法
}
2. 定义成员变量
[修饰符] 数据类型 变量名 [=值];
3. 定义成员方法
[修饰符] [返回值类型] 方法名 ([参数类型 参数名1 , 参数类型 参数名2 , ......]) {
//方法体
...
return 返回值; //返回值类型为void时,return及返回值可省略
}
*/
public class Person{
int age;
void speak(){
System.out.println("我今年" + age +"岁!");
}
}
- 在某一个方法中允许定义的局部变量与成员变量同名,此时方法中通过变量名访问到的是局部变量,而非成员变量
public class Person{
int age = 10;
void speak(){
int age = 20;
System.out.println("我今年" + age +"岁!");
//此时有程序调用speak()方法时,输出的值为20
}
}
1.3 对象的创建
Java程序中使用 new 关键字来创建对象
//类名 对象名称 = new 类名();
Person p = new Person();
- 栈内存用于存放基本类型的变量和对象的引用变量,堆内存用于存放由 new 创建的对象和数组
class Person{
int age;
void speak(){
System.out.println("我今年" + age +"岁!");
}
}
public class Main{
public static void main(String[] args) {
Person p1 = new Person();
p1.age = 18;
p1.speak();
//我今年18岁!
}
}
- 还可以使用创建的对象本身来引用对象成员,这种方式是在通过 new 关键字创建实例对象的同时就访问了对象的某个成员,并且在创建后只能访问其中某一个成员,而不能像对象引用那样可以访问多个对象成员。同时,由于没有对象引用的存在,在完成某一个对象成员的访问后,该对象就会变成垃圾对象
匿名对象:一次性的
//new 类名().对象成员
new Person().speak();
- 当没有任何变量引用这个对象时,它就会变成垃圾对象,不能再被使用
{
//使用变量p1引用了一个Person类型的对象
//当代码执行完毕,变量p1就会超出其作用域而被销毁
//此时Person类型的对象将因为没有被任何变量引用而变成垃圾
Person p1 = new Person();
...
}
{
//使用变量p2引用了一个Person类型的对象,接着将变量p2的值设为null
//设为null后,被p2所引用的Person对象就会失去引用,成为垃圾对象
Person p2 = new Person();
...
p2 = null;
...
}
1.4 注意的地方
1.4.1 每个对象都有name,age,p1和p2需要各自赋值
class Person{
String name;
int age;
void pname() {System.out.println("我的名字是:" + name);}
void speak() {System.out.println(",我今年" + age +"岁!");}
}
public class Main {
public static void main(String[] args) {
/*Person p1 = null; 这个引用不指向任何对象*/
Person p1 = new Person();
Person p2 = new Person();
p1.name = "Jack";
p1.pname();
p2.pname();
}
1.4.2 p2这个引用指向p1这个引用所指的对象
Person p1 = new Person();
Person p2 = p1;
p2.name = "Jack";
p1.pname();
p2.pname();
1.4.3 一个引用不可以同时指向多个对象,以最后一次为准
Person p1 = new Person();
p1 = new Person();
p1 = new Person();
p1.name = "Jack";
p1.pname();
1.4.4 静态成员变量
class Test{
public static int count;//静态成员变量
}
public class Main {
public static void main(String[] args) {
Test t1 = new Test();
Test t2 = new Test();
t1.count++;
System.out.println(t1.count);
t2.count++;
System.out.println(t2.count);
Test.count++;//可以不用new新的对象
System.out.println(Test.count);
}
}
1.4.5 普通方法内部不能定义静态变量
1.4.6 普通方法可以调用静态方法
class Test{
int count;
public static void staticFunc(){
System.out.println("hello");
}
void print(){
staticFunc();
}
}
public class Main {
public static void main(String[] args) {
Test test = new Test();
test.print();
}
}
1.4.7 静态方法不能调用普通方法
1.4.8 静态方法不依赖对象
public static void main(String[] args) {
Test test = new Test();
test = null;
test.staticFunc();
//仍能输出hello
}
1.4.9
class Person1{
public String toString(){
return "hello";
}
}
public class testfeng {
public static void main(String[] args) {
Person1 p1 = new Person1();
System.out.println(p1);
//输出hello
}
2. 类的封装
2.1 为什么封装
在设计一个Java类时,应该对成员变量的访问做出一些限定,不允许外界随意访问,这就需要实现类的封装
class Person{
int age;
void speak(){
System.out.println("我今年" + age +"岁!");
}
}
public class Main {
public static void main(String[] args) {
Person p1 = new Person();
p1.age = -20;
p1.speak();
//-20不符合现实
}
}
2.2 实现封装
在定义一个类的时候,将类中的属性私有化,即使用private关键字来修饰,如果外界想要访问私有属性,需要提供一些使用 public 修饰的公有方法,其中包括用于获取属性值 getXxx() 方法和设置属性值的 setXxx() 方法
class Person{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if(age <= 0){
System.out.println("输入的年龄不正确!");
}else{
this.age = age;
}
}
void speak(){
System.out.println("我的名字是:" + name + ",我今年" + age +"岁!");
}
}
public class Main {
public static void main(String[] args) {
Person p1 = new Person();
p1.setName("张三");
p1.setAge(-20);
p1.speak();
}
}
3. 方法的重载和递归
3.1 重载
Java允许在一个程序中定义多个方法名相同,但是参数的类型或个数不同的方法,这就是方法的重载
public static int add(int x,int y){
return x+y;
}
public static int add(int x,int y,int z){
return x+y+z;
}
public static double add(double x,double y){
return x+y;
}
public static void main(String[] args) {
System.out.println("sum1= " + add(1,2));
System.out.println("sum2= " + add(1,2,3));
System.out.println("sum3= " + add(0.5,0.3));
}
3.2 递归
方法的递归:是指在一个方法的内部调用自身的过程。递归必须有结束条件,不然会陷入无限递归的状态,永远无法结束调用
public static int getSum(int n){
if(n == 1){//满足条件,递归结束
return 1;
}
int temp = getSum(n-1);
return temp+n;
}
public static void main(String[] args) {
System.out.println("sum = " + getSum(4));//求1~4的和
//sum = 10
}
4. 构造方法
实例化一个类的对象后,如果要为这个对象中的属性赋值,则必须直接访问对象的属性或调用 setXxx() 方法。如果需要在实例化对象的同时就为这个对象的属性进行赋值,可以通过构造方法来实现。构造方法(也被称为构造器),是类的一个特殊成员,它会在类实例化对象时被自动调用。
4.1 定义
定义构造方法需要满足三个条件:
- 方法名与类名相同
- 在方法名的前面没有返回值类型的声明
- 在方法中不能使用 return 语句来返回一个值,但可以单独写 return 语句来作为方法的结束
无参的构造方法:
class Person{
public Person(){
System.out.println("无参的构造方法");
}
}
public class Main {
public static void main(String[] args) {
Person p1 = new Person();
//new Person() 实例化Person对象时会自动调用该类的构造方法
}
}
还可以定义有参的构造方法,通过有参的构造方法就可以实现对属性的赋值
class Person{
int age ;
public Person(){
System.out.println("无参的构造方法");
}
public Person(int a){
age = a;
}
void speak(){
System.out.println("我今年" + age +"岁!");
}
}
public class Main{
public static void main(String[] args) {
Person p1 = new Person(20);
p1.speak();
}
}
4.2 构造方法的重载
在一个类中可以定义多个构造方法,只要每个构造方法的参数类型或参数个数不同即可
class Person{
String name;
int age ;
public Person(int a){
age = a;
}
public Person(String n,int a){
name = n;
age = a;
}
void speak(){
System.out.println("我今年" + age +"岁!");
}
void say(){
System.out.println("我的名字是:" + name +",今年" + age +"岁!");
}
}
public class Main {
public static void main(String[] args) {
Person p1 = new Person(20);
Person p2 = new Person("Jack",23);
p1.speak();
p2.say();
}
}
4.3 注意的地方
Java中每个类都至少有一个构造方法,如果一个类中没有显式地定义构造方法,系统会自动为这个类创建一个默认的构造方法,这个默认的构造方法没有参数,在其方法体中没有任何代码,即什么也不做
//这两种写法效果相同
class Test01{
}
class Test02{
public Test02(){
}
}
5. this关键字和static关键字
点击它 → this 关键字和 static 关键字