目录
封装
封装引入
private修饰符
this关键字
构造函数
JavaBean
标准JavaBean
JavaBean中的成员与数据库的关系
static关键字
static基本使用
static关键字访问特点
可变参数
对象数组与传值/址调用
对象数组
传值调用与传址调用
命令行参数
封装
封装引入
面向对象三大特性:封装、继承和多态
在Java中,封装是将一类事物的属性和方法放到一个class
类中,例如Person类
package com.epsda.java_class;
public class Person {
// 属性
String name;
int age;
Birthday birthday;
// 方法
public void print(){
System.out.println("name = " + name + " " + "age = " + age + " " + "birthday: " + birthday.year + "/" + birthday.month + "/" + birthday.day);
}
}
但是Person类
中的成员此时可以被随意访问和修改,为了防止这种问题,从而出现了访问修饰符private
private
修饰符
使用private
修饰符修饰的成员无法在类外被访问
package com.epsda.java_private;
public class Person {
// 被priavte修饰后无法在类外访问
private int age;
private String name;
}
package com.epsda.java_private;
public class java_private {
public static void main(String[] args) {
Person person = new Person();
// 被priavte修饰后无法在类外访问
// person.age = 10;
// person.name = "张三";
}
}
但是封装之后需要对外提供使用的接口,在Java中称为get
和set
方法
this
关键字
当方法的局部变量和成员变量重名时,可以使用this
关键字指代成员变量,防止出现重名时的访问均为局部变量
this
关键字指代的是调用对象,其地址和对象地址相同
package com.epsda.java_private;
public class Person {
// 展示this和对象地址
public void showThis(){
System.out.println(this);
}
}
package com.epsda.java_private;
public class java_private {
public static void main(String[] args) {
Person person2 = new Person();
System.out.println(person2);
person2.showThis();
}
}
输出结果:
com.epsda.java_private.Person@154617c
com.epsda.java_private.Person@154617c
结合get
/set
方法,this
关键字的使用
package com.epsda.java_private;
public class Person {
// 被priavte修饰后无法在类外访问
private int age;
private String name;
// 提供get和set方法
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;
}
}
构造函数
Java中创建对象时需要使用new
,而new
后面的实际上是在调用构造函数构造对象,如果类没有显式写构造函数,那么JVM会隐式生成一个无参数的构造函数,但是如果显式写了构造函数(包括无参数和有参数),那么编译器就不会再生成
package com.epsda.java_private;
public class Person {
// 被priavte修饰后无法在类外访问
private int age;
private String name;
// 构造函数
// 无参数构造
public Person() {
}
// 有参数构造
public Person(int age, String name) {
this.age = age;
this.name = name;
}
}
当无参数构造函数和有参数构造函数共存时,此时出现方法重载现象,如果创建对象不传入参数,则调用无参数构造函数,否则调用有参数构造函数
package com.epsda.java_private;
/**
* ClassName: java_private
* Package: com.epsda.java_private
* Description:
*
* @author 憨八嘎
* @version v1.0
*/
public class java_private {
public static void main(String[] args) {
// 调用无参数构造函数
Person person = new Person();
// 通过get方法获取属性值
System.out.println(person.getName() + " " + person.getAge());
// 通过set方法设定属性值
person.setAge(10);
person.setName("李四");
System.out.println(person.getName() + " " + person.getAge());
// 调用有参数构造函数
Person person1 = new Person(10, "张三");
// 通过get函数获取属性值
System.out.println(person1.getName() + " " + person1.getAge());
}
}
输出结果:
null 0
李四 10
张三 10
JavaBean
标准JavaBean
JavaBean是Java语言编写类的一种标准规范。符合JavaBean
的类,要求:
-
类必须是具体的(非抽象
abstract
)和公共的,public class
类名 -
并且具有无参数的构造方法,有参构造
-
成员变量私有化,并提供用来操作成员变量的
set
和get
方法。
在Java项目中,一般有以下包及对应的功能
-
com.epsda.controller
-> 专门放和页面打交道的类(表现层) -
com.epsda.service
-> 专门放业务处理的类 (业务层) -
com.epsda.dao
-> 专门放和数据库打交道的类(持久层) -
com.epsda.pojo
-> 专门放JavaBean类 -
com.epsda.utils
-> 专门放工具类
对于上方的Person类来说,即为一个标准的JavaBean结构
package com.epsda.java_private;
/**
* ClassName: Person
* Package: com.epsda.java_private
* Description:
*
* @author 憨八嘎
* @version v1.0
*/
public class Person {
// 被priavte修饰后无法在类外访问
private int age;
private String name;
// 构造函数
// 无参数构造
public Person() {
}
// 有参数构造
public Person(int age, String name) {
this.age = age;
this.name = name;
}
// 提供get和set方法
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;
}
}
JavaBean中的成员与数据库的关系
-
类名 -> 表名
-
属性名 -> 列名
-
对象 -> 表中每一行数据
-
属性值 -> 表中单元格中的数据
对于Person
类来说,Person
表结构如下
name | age |
---|---|
张三 | 10 |
李四 | 10 |
static
关键字
static
基本使用
当一个成员是多个对象共享时,可以使用static
关键字对该成员进行修饰
static
修饰的成员可以直接使用类名调用
定义一个Student
类,教室学生共用,所以可以设置为static
,其他为每一个对象特有的则可以不设置为static
package com.epsda.java_static;
/**
* ClassName: Student
* Package: com.epsda.java_static
* Description:
*
* @author 憨八嘎
* @version 1.0
*/
public class Student {
// 学生特有属性
private String name;
private int age;
// 学生共有属性
private static int classroom;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public static int getClassroom() {
return classroom;
}
public static void setClassroom(int classroom) {
Student.classroom = classroom;
}
public void print() {
System.out.println(name + " " + age + " " + classroom);
}
}
测试类
package com.epsda.java_static;
/**
* ClassName: java_static
* Package: com.epsda.java_static
* Description:
*
* @author 憨八嘎
* @version 1.0
*/
public class java_static {
public static void main(String[] args) {
Student student1 = new Student("张三", 18);
Student student2 = new Student("李四", 20);
// 两个学生在一个班级时,直接用类名调用,而不是每一个单独设置
Student.setClassroom(112);
student1.print();
student2.print();
}
}
输出结果:
张三 18 112
李四 20 112
static
关键字访问特点
static
关键字修饰的成员(成员变量和成员函数)与类同时加载到内存,所以会早于普通的成员变量,并且加载到内存堆区的静态域中,所以,在调用时需要注意下面的情况:
-
非静态成员可以访问静态成员
package com.epsda.java_static; /** * ClassName: java_static * Package: com.epsda.java_static * Description: * * @author 憨八嘎 * @version 1.0 */ public class java_static { public static void main(String[] args) { } // 非静态成员 public void func1() { // 非静态成员可以直接访问静态成员 func2(); } // 静态成员 public static void func2(){ } }
-
静态成员不可以访问非静态成员,除非创建对象,因为对象创建后,非静态成员也被创建了
package com.epsda.java_static; /** * ClassName: java_static * Package: com.epsda.java_static * Description: * * @author 憨八嘎 * @version 1.0 */ public class java_static { public static void main(String[] args) { // func1(); 非静态成员不可以被静态成员直接调用 java_static js = new java_static(); js.func1();// 但是可以通过对象调用 } // 非静态成员 public void func1() { } }
-
非静态成员可以访问非静态成员,静态成员可以访问静态成员
static
成员在开发中一般可以指定一个工具类,工具类是指该类中是某一种对象的常见方法,该方法被修饰为static
,便于使用类名直接调用。特殊地,工具类的构造方法全是private
修饰
可变参数
在Java中,如果不确定函数参数的具体个数,可以使用可变参数进行代替,声明可变参数的方式如下
数据类型...变量名
例如,求出n个整数相加之和
package com.epsda.multiple_variables;
/**
* ClassName: Multi_variables
* Package: com.epsda.multiple_variables
* Description:
*
* @author 憨八嘎
* @version 1.0
*/
public class Multi_variables {
public static void main(String[] args) {
int ans1 = sum(1,2,3);
int ans2 = sum(1,2,3,4);
int ans3 = sum(1,2,3,4,5);
System.out.println("ans1 = " + ans1);
System.out.println("ans2 = " + ans2);
System.out.println("ans3 = " + ans3);
}
public static int sum(int...arr) {
int ans = 0;
for (int i = 0; i < arr.length; i++) {
ans += arr[i];
}
return ans;
}
}
输出结果:
ans1 = 6
ans2 = 10
ans3 = 15
在Java中,可变参数实际上是一个数组类型,所以可以使用数组的方式进行遍历
一个形参位置只能有一个可变参数,并且如果有其他参数时,可变参数必须放在最后一个参数的位置
package com.epsda.multiple_variables;
/**
* ClassName: Multi_variables
* Package: com.epsda.multiple_variables
* Description:
*
* @author 憨八嘎
* @version 1.0
*/
public class Multi_variables {
public static void main(String[] args) {
// 第一个实参给函数的一个形参,剩下的全给可变参数
String ans = concat("-", "字符串1", "字符串2");
System.out.println("ans = " + ans);
}
// 多个参数,可变参数放在最后
public static String concat(String regex, String... arr) {
String ans = "";
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
ans += arr[i];
} else {
ans += arr[i] + regex;
}
}
return ans;
}
}
输出结果:
ans = 字符串1-字符串2
对象数组与传值/址调用
对象数组
所谓对象数组,即数组中的元素是对象
package com.epsda.array;
/**
* ClassName: object_array
* Package: com.epsda.array
* Description:
*
* @author 憨八嘎
* @version 1.0
*/
public class object_array {
public static void main(String[] args) {
// 创建对象数组
Person arr[] = new Person[3];
// 创建对象并存入数组中
for (int i = 0; i < arr.length; i++) {
// 数组中的每一个元素都是Person的匿名对象
arr[i] = new Person(18,"姓名");
System.out.println(arr[i].getName()+" "+arr[i].getAge());
}
}
}
传值调用与传址调用
在Java中,基本数据类型实参传递给方法的形参时只是传值调用,但是对于引用类型来说,传递给方法形参的实参都是地址,所以是传址调用
package com.epsda.call;
/**
* ClassName: Call
* Package: com.epsda.call
* Description:
*
* @author 憨八嘎
* @version 1.0
*/
public class Call {
public static void main(String[] args) {
// 基本数据类型
int a = 10;
int b = 20;
sum(a, b);
System.out.println("a = " + a);// 方法内修改不影响main函数中的a和b,传值调用
System.out.println("b = " + b);
System.out.println("---------------------------");
// 引用数据类型
int arr[] = {2, 3, 4, 5};
change(arr, arr1);// 方法内的修改影响main函数中的引用类型
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
// 传值调用
public static void sum(int a, int b) {
a = 20;
b = 40;
System.out.println("a = " + a);
System.out.println("b = " + b);
}
// 传址调用
public static void change(int[] arr, String arr1) {
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
System.out.print(arr[i] + " ");
}
System.out.println();
}
}
输出结果:
a = 20
b = 40
a = 10
b = 20
---------------------------
0 1 2 3
0 1 2 3
需要注意的是
String
类型引用,在Java中,字符串是不可改变的量,所以如果在方法内尝试对实参的String
类型值进行改变并不会影响实参。每一个字符串都有对应的地址,当指向字符串的实参传入方法中,在方法内改变该实参对应的形参内容只是改变形参指向的地址值,并不会改变实参指向的地址值,本质这里还是传值调用,例如:package com.epsda.call; /** * ClassName: Call * Package: com.epsda.call * Description: * * @author 憨八嘎 * @version 1.0 */ public class Call { public static void main(String[] args) { String arr1 = "字符串"; change(arr1);// 方法内的修改不影响main函数arr1 System.out.print(arr1); } public static void change(String arr1) { arr1 = "修改字符串"; System.out.print(arr1); System.out.println(); } } 输出结果: 修改字符串 字符串
命令行参数
Java中的main方法有一个形参String[] args,当需要临时测试方法时,可以通过这个形参传递值
public class CommandParam{
public static void main(String[] args){
for(int i = 0; i < args.length; i++){
System.out.println("第" + (i+1) + "个参数的值是:" + args[i]);
}
}
}
在命令行中输入命令:
javac CommandParam.java
java CommandParam 字符串1 字符串2
此时即可输出下面的内容: