热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java入门级学习的每日总结(6):类和对象、static关键字、构造函数——万字攻略。

1.类与对象的初步认知面向过程:注重过程,在整个过程中所涉及的行为,就是功能。面向对象:注重对象,也就是参与过


1. 类与对象的初步认知


        面向过程:注重过程,在整个过程中所涉及的行为,就是功能。
        面向对象:注重对象,也就是参与过程所涉及到的主体。是通过逻辑将一个个功能实现连接起来。



2. 类和类的实例化


        类:一组具有相同特征的对象的抽象,对象就是这一类具体化的一个实例,类中定义了所有该类对象所共同具备的属性和方法。

        类相当于一个模板,对象是由模板产生的样本。一个类,可以产生无数的对象。
        所有类的对象都是引用数据类型,对于引用类型来说,默认值为 null 。Java 使用关键字 class 来声明类。



 基本语法

// 创建类
class {field;//成员属性method();//成员方法
}
// 实例化对象
<对象名> &#61; new ();

        class 为定义类的关键字&#xff0c;ClassName 为类的名字&#xff0c;{} 中为类的主体。

        类中的元素称为&#xff1a;成员属性。

        类中的函数称为&#xff1a;成员方法。



类的实例化

//代码示例
class Person {public int age; //成员属性 实例变量public String name;public String sex;public void eat() { //成员方法System.out.println("吃饭!");}public void sleep() {System.out.println("睡觉!");}
}public class Main{public static void main(String[] args) {Person person &#61; new Person(); //通过new实例化对象person.eat(); //成员方法调用需要通过对象的引用调用person.sleep();//产生对象 实例化对象Person person2 &#61; new Person();Person person3 &#61; new Person();}
}
//输出结果
吃饭!
睡觉!

注意事项
        1. new 关键字用于创建一个对象的实例。
        2. 使用 . 来访问对象中的属性和方法。
        3. 同一个类可以创建对个实例。



3. 类的成员


        类的成员可以包含以下&#xff1a;字段方法代码块内部类接口等。



3.1 字段 / 属性 / 成员变量


        在类中&#xff0c;但是方法外部定义的变量。这样的变量我们称为 "字段" 或 "属性" 或 "成员变量" (三种称呼均可)。用于描述一个类中包含哪些数据。

class Person {public String name; // 字段public int age; // 字段
}
class Test {public static void main(String[] args) {Person person &#61; new Person();System.out.println(person.name);System.out.println(person.age);}
}
// 执行结果
null
0

注意事项
        1. 使用 . 访问对象的字段。
        2. "访问" 既包含读&#xff0c;也包含写。
        3. 对于一个对象的字段如果没有显式设置初始值&#xff0c;那么会被设置一个默认的初值。

默认值规则
        1. 对于各种数字类型&#xff0c;默认值为 0
        2. 对于 boolean 类型&#xff0c;默认值为 false
        3. 对于引用类型(String&#xff0c;Array&#xff0c;以及自定制类)&#xff0c;默认值为 null


认识 null


        null 在 Java 中为 "空引用"&#xff0c;表示不引用任何对象。类似于 C 语言中的空指针。如果对 null 进行 . 操作就会引发异常。

        如果报错 NullPointerException ->空指针异常&#xff0c;一定使用了一个值为 null 的引用去访问成员属性或者成员方法了。&#xff08;null 访问 static 属性不报错&#xff09;

class Person {public String name; //成员属性public int age; //成员属性
}
class Test {public static void main(String[] args) {Person person &#61; new Person();System.out.println(person.name.length()); // 获取字符串长度}
}
// 执行结果
Exception in thread "main" java.lang.NullPointerException

字段就地初始化


         不使用默认值&#xff0c;而是显式设定初值的操作。

class Person {public String name &#61; "张三"; //赋初值public int age &#61; 18; //赋初值}class Test {public static void main(String[] args) {Person person &#61; new Person();System.out.println(person.name);System.out.println(person.age);}
}
// 执行结果
张三
18


3.2 方法 (method)


        方法&#xff1a;用于描述一个对象的行为。

class Person {public int age &#61; 18;public String name &#61; "张三";public void show() {System.out.println("我叫" &#43; name &#43; ", 今年" &#43; age &#43; "岁");}
}class Test {public static void main(String[] args) {Person person &#61; new Person();person.show(); //调用方法}
}
// 执行结果
我叫张三, 今年18岁

        此处 show 成员方法是和 person 实例对象相关联的。如果创建了其他实例&#xff0c;那么 show 的行为就会发生变化。

Person person2 &#61; new Person();
person2.name &#61; "李四";
person2.age &#61; 20;
person2.show(); //其他实例调用方法
// 执行结果
我叫李四, 今年20岁


3.3 static 关键字&#xff08;重点理解&#xff09;——看见static&#xff0c;本能反应&#xff0c;和对象无关


3.3.1 staic修饰的属性&#xff08;称为类属性&#xff09;


        Java静态属性和类相关&#xff0c;和具体的实例对象无关。

        当一个实例变量被 static 关键字修饰&#xff0c;他就表示类的属性&#xff0c;该类的所有对象共享这个属性&#xff0c;所有对象的属性值都一样。

        static 修饰的属性在 JVM 方法区中存储&#xff0c;所有该类对象共享此属性。

class Person{String name; // 成员变量&#xff0c;实例变量必须通过该类的对象来访问int age; // 人这个属性中&#xff0c;需要有单独个体&#xff0c;才能得出该个体的name、agestatic String country; // 很多对象在堆中共有的成员属性countryvoid show() { // 成员方法&#xff0c;实例方法&#xff0c;也是必须通过对象来访问System.out.println("name &#61; " &#43; name &#43;",age &#61; " &#43; age &#43; ",country &#61; " &#43; country);}
}public class Main{public static void main(String[] args) {Person per1 &#61; new Person();per1.name &#61; "张三";per1.age &#61; 20;per1.show();Person per2 &#61; new Person();per2.name &#61; "李四";per2.age &#61; 18;per2.show();}
}
//输出结果
name &#61; 张三,age &#61; 20,country &#61; 中国
name &#61; 李四,age &#61; 18,country &#61; 中国


直接通过类名称访问 static 修饰的属性&#xff0c;无需通过对象访问。 


class Person{static String country &#61; "中国"; //很多对象在堆中共有的成员属性country}
}public class Main{public static void main(String[] args) {Person per1 &#61; new Person();System.out.println(Person.country); //用 类 访问static成员属性System.out.println(per1.country); //用 对象 访问static成员属性}
}
//输出结果
中国
中国

问题1&#xff1a;Java中能否在一个方法内部&#xff0c;定义一个 static 变量&#xff1f;

答&#xff1a;不能&#xff0c;方法中定义的变量全部都是局部变量&#xff0c;局部变量在栈中存储&#xff0c;而static 变量在方法区&#xff0c;属性不可能同时存在于栈与方法区中。静态 main 方法中同样不能定义static 变量

问题2&#xff1a;定义Person per2 &#61; null&#xff1b;

             执行 per2.country 是否报错"空指针异常";

public static void main(String[] args) {Person per2 &#61; null;System.out.println(per2.country);
}
class Person {static String country &#61; "中国";
}
//输出结果
中国

答&#xff1a;可以&#xff0c;static 属性称为类属性&#xff0c;通过类名称直接访问。故没有对象也可以调用&#xff08;包含类的null引用&#xff09;&#xff0c;而不会出现 NullPointerException ->空指针异常报错。



static 与 final 的区别


class Person {//成员常量&#xff0c;都在堆中存储&#xff0c;必须在定义时赋值final int age &#61; 18;//静态变量&#xff0c;在方法区中存储&#xff0c;所有Person的对象共享这个country属性static String country &#61; "中国";
}

        age 这个属性为成员常量&#xff0c;在类定义的时候就已赋值为18了。Person的所有对象都有age属性&#xff0c;且值都是18。把他定义为 static final &#xff0c;可以节省空间&#xff0c;并且所有Person对象共享这个属性&#xff0c;全局唯一。

        故在类中定义常量&#xff0c;一般使用全局常量&#xff0c;用 static final 共同修饰。



常量的命名规则


        所有单词全部大写&#xff0c;多个单词使用下划线分隔。

        如&#xff0c;static final String STUDENT_SCHOOL &#61; "清华大学"&#xff1b;



总结

  1. static 变量称为类属性&#xff0c;在方法区中存储&#xff0c;该类的所有对象共享此变量。
  2. 若在类中定义了常量(定义时赋值)&#xff0c;一般我们使用 static 和 final 共同修饰变成全局常量。
  3. 要使用类属性&#xff0c;我们通常直接通过类名称 . 属性名称&#xff0c;不推荐使用对象来调用类属性&#xff0c;这样不规范。


3.3.2 staic修饰的方法&#xff08;类方法、工具方法&#xff09;


        staic修饰的方法&#xff0c;也是通过类名称直接访问的方法&#xff0c;没有对象也能访问。

        类方法&#xff0c;如主方法


        工具方法&#xff0c;如Arrays.sort(int[])、Arrays.copyOf(int[])

        都是Arrays对外提供的操作数组的方法&#xff0c;将其设计为 static 方法



问题1&#xff1a;为何主方法是 static 方法&#xff1f;

答&#xff1a;主方法是程序的入口。如果主方法是成员方法&#xff0c;则需要 new 出对象调用&#xff0c;但没有程序入口&#xff0c;就产生不了对象。

        程序从主方法开始运行&#xff0c;主方法要能够调用其他方法&#xff0c;所以设计为 static &#xff0c;直接调用而不用产生对象。


问题2&#xff1a;静态方法能否访问成员变量、成员方法&#xff1f;

答&#xff1a;不能&#xff0c;成员方法、成员变量必须通过对象来调用。 static 里面没有该类对象&#xff0c;所以无法调用。


问题3&#xff1a;成员方法能否访问静态变量、静态方法&#xff1f;

答&#xff1a;可以&#xff0c;有对象才能调用成员方法&#xff0c;static 没对象都能调用&#xff0c;更何况有对象&#xff0c;那就更能调用了。


问题4&#xff1a;外部类能否使用 static 关键字修饰&#xff1f;

答&#xff1a;不能&#xff0c;编译出错。类定义出来就是要产生对象的&#xff0c;static 类没对象&#xff0c;就能调用。



总结

1. 在静态方法中只能调用静态方法或者静态属性&#xff0c;static家族之间可以相互调用。从中不能直接调用成员方法和成员属性&#xff0c;必须通过对象来调用。

2. 在成员方法中既可以调用成员方法&#xff0c;也可调用静态方法(此时都已经产生了该类对象&#xff0c;一定是可以访问静态域的)。



4. 封装


 保护性和易用性



4.1 private&#xff08;实现封装的方法之一&#xff09;


        在Java中&#xff0c;所谓的权限修饰符&#xff0c;指的是修饰的属性、方法、类&#xff0c;到底可见的范围有多大。其中一共有四大访问修饰符&#xff0c;可见的范围又小到大依次为&#xff1a;

        private


        private 私有的&#xff0c;被private修饰的属性和方法&#xff0c;只在当前类的内部可见&#xff0c;出了类就对外部就完全隐藏了&#xff0c;外部不知道有其存在。

        public 公共的&#xff0c;公开的被public修饰的属性和方法&#xff0c;在当前程序(项目)中都是可见的&#xff0c;都是可以使用的。



4.2 getter 和 setter 方法


类比现实

        对于银行卡这个类来说&#xff0c;银行卡有卡号&#xff0c;余额&#xff0c;密码这三个属性。如果这三个属性直接暴露在外部&#xff0c;显然不安全&#xff0c;不能让这些属性通过对象直接就访问了。 


想在类的外部去使用这些私有属性&#xff0c;需要使用类提供的 getter (取值)和 setter (修改值)。

// 公共访问权限&#xff0c;主类&#xff0c;这个类在当前项目中都是可见的
public class PrivateTest {public static void main(String[] args) {Bank bank &#61; new Bank();// 当password属性被private之后&#xff0c;对于这个属性就是一个保护// 类的外部要想使用这个属性&#xff0c;必须按照我的规则去使用(getter和setter)bank.setPassword();System.out.print("修改后的密码为:");System.out.println(bank.getPassword());}
}// 银行类,缺省修饰符&#xff0c;包访问权限
class Bank {private int cardNum; // 卡号private double sal; // 余额private String password &#61; "123456"; // 密码// alt &#43; insert 快速生成getter和setter方法// get&#43;属性名称 &#61; 方法命名public int getCardNum() { //取值return cardNum;}public double getSal() { //取值return sal;}public String getPassword() { //取值return password;}public void setPassword() {Scanner scanner &#61; new Scanner(System.in);int count &#61; 0;// 验证当前密码是否正确才能修改while (true) {System.out.println("请输入您现在的旧密码:");String oldPass &#61; scanner.nextLine();count &#43;&#43;;// 所有引用类型的对象比较使用equals方法if (oldPass.equals(password)) {// 密码输入正确&#xff0c;修改密码System.out.println("密码正确&#xff0c;正在改密码");System.out.println("请输入您的新密码&#xff1a;");String newPass &#61; scanner.nextLine();password &#61; newPass;System.out.println("密码修改成功!");break;} else {// 输入密码有误System.out.println("密码错误&#xff0c;请查证后再试");if (count &#61;&#61; 3) {System.out.println("尝试次数过多&#xff0c;银行卡已经锁定");break;}}}}
}



问题1&#xff1a;private 能否修饰外部类&#xff1f;

答&#xff1a;不能&#xff0c;类定义出来就是为了产生对象&#xff0c;让外部使用。用 private 封装&#xff0c;在外面就看不到了&#xff0c;从而不能使用对象。



5. 构造方法


        构造方法是类中非常特殊的一类方法&#xff0c;使用关键字 new 实例化对象时&#xff0c;实际上就调用的是该类的构造方法。构造方法的作用就是产生对象。

        使用关键字 new 产生一个对象时&#xff0c;大致分为以下两步&#xff1a;

        1.为对象在堆中分配空间
        2.调用对象的构造方法为对象成员变量赋值



5.1 基本语法


        构造方法语法规则&#xff1a;
        1. 方法名称与类名称完全相同
        2. 构造方法没有返回值声明(无void)。
        3. 一个类中至少存在一个构造方法&#xff0c;若没有显示定义&#xff0c;编译器会生成—个默认的无参构造



定义构造方法

public class TestClass {public static void main(String[] args) {Person per &#61; new Person();}
}class Person {private String name;private int age;public Person() { //构造方法的定义System.out.println("Person的无参构造");}
}
//输出结果
Person的无参构造

若没有定义构造方法&#xff0c;编译器会自动生成一个。

当类中自定义了构造方法&#xff0c;默认的无参构造就不再生成。

构造方法在内存空间赋值

构造方法的重载

构造方法是为了类中的成员变量赋值的&#xff0c;此时的重载只可能是参数的个数不同。

&#xff08;成员变量的类型在类定义时就指定好了&#xff0c;只是初始化的变量个数不同。&#xff09;

public class TestClass {public static void main(String[] args) {Person per1 &#61; new Person();Person per2 &#61; new Person("小明");Person per3 &#61; new Person("小明", 18);// 这三个对象构造方法都已经调用结束&#xff0c;初始化完成}
}class Person {private String name;private int age;private String sex;public Person() { //无参构造方法的定义//mame &#61; null;age &#61; 0;sex &#61; null; //首行赋默认值System.out.println("Person的无参构造");}public Person(String n) { //传一个参数//mame &#61; null;age &#61; 0;sex &#61; null; //首行赋默认值name &#61; n;System.out.println("name &#61; " &#43; name);System.out.println("Person的一个参数的有参构造");}public Person(String n, int a) { //传两个参数//mame &#61; null;age &#61; 0;sex &#61; null; //首行赋默认值name &#61; n;age &#61; a;System.out.println("name &#61; " &#43; name &#43; ",age &#61; " &#43; age);System.out.println("Person的两个参数的有参构造");}
}
//输出结果
Person的无参构造
name &#61; 小明
Person的一个参数的有参构造
name &#61; 小明,age &#61; 18
Person的两个参数的有参构造

成员变量定义时赋初值

        成员变量只有在产生对象时&#xff0c;才会在堆中分配空间&#xff0c;然后调用构造方法赋值。



问题&#xff1a;此处对象 per1 能否调用构造方法 Person &#xff1f;

答&#xff1a;不能&#xff0c;报错 java&#xff1a;找不到符号。
                  符号&#xff1a;方法 Person()
                  位置&#xff1a;类型为Person的变量 per1

        自己调用自己的构造方法&#xff0c;JVM 产生对象时调用构造方法&#xff0c;对象实例化结束&#xff0c;无法在程序中手动调用构造方法再次实例化对象。



5.2 this 关键字


        this 关键字表示当前对象的引用



5.2.1 this 调用当前对象的成员变量


public class ThisTest {public static void main(String[] args) {Student student &#61; new Student("小明", 20, "男");student.show();}
}class Student {private String name; private int age;private String sex;public Student(String name, int age, String sex) {name &#61; name; //就近匹配age &#61; age;sex &#61; sex;System.out.println("Student类的有参构造");}public void show() {System.out.println("name &#61; " &#43; name &#43; ",age &#61; " &#43; age &#43; ",sex &#61; " &#43; sex);}
}
//输出结果
Student类的有参构造
name &#61; null,age &#61; 0,sex &#61; null

        程序的设计理念&#xff0c;就近匹配原则&#xff0c;编译器会找到最近的相同名称的变量在哪。上述情况&#xff0c;形参自己等于了自己&#xff0c;对类中的成员变量没有任何影响。

        如何打破就近匹配原则&#xff0c;从类中找同名变量&#xff1f;——>使用 this 关键字。形参的值给了成员变量。

//使用 this 关键字&#xff0c;改正上述问题
public Student(String name, int age, String sex) {this.name &#61; name;this.age &#61; age;this.sex &#61; sex;System.out.println("Student类的有参构造");}
//输出结果
Student类的有参构造
name &#61; 小明,age &#61; 20,sex &#61; 男



5.2.2 this 调用类中的方法


1. this 调用普通成员方法


public class ThisTest {public static void main(String[] args) {Student student &#61; new Student();student.fun();}
}class Student {private String name;private int age;private String sex;public void test() {System.out.println("Student类的test成员方法");}public void fun() {//此处没有用对象调用 test();test();System.out.println("Student类的fun成员方法");}
}
//输出结果
Student类的test成员方法
Student类的fun成员方法

此处 test() 未使用对象却依旧可以调用&#xff0c;原因是编译器编译后默认加上 this &#xff0c;使其变成当前对象的引用 this.test() 。



2. this 表示构造方法间的相互调用


        若不同参数的构造方法之间出现了重复的调用&#xff0c;可以使用this(参数)调用其他的构造方法。

public Student() {System.out.println("********************");}public Student(String name) {//调用无参构造this();this.name &#61; name;}public Student(String name, int age) {this(name);this.age &#61; age;}


 


推荐阅读
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
author-avatar
mobiledu2502916503
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有