Java基础教程——封装
面向对象的三大特征
- 封装:encapsulation
- 继承:inheritance
- 多态:polymorphism
封装
类是一个最基本的封装
封装的好处:
- 数据安全:保证数据安全
- 方便调用:提供清晰的对外接口,方便外界调用
- 降低耦合:类内部的实现可以修改,不影响其他类
电脑主机就是一个封装的例子,内存等硬件封装在机箱中,对外提供显示器接口、电源接口、USB接口,加根内存条不影响外界的使用。
良好的封装:尽可能限制类和成员的可访问性 。
对于代码而言:对象的状态信息被隐藏在内部,外界无法直接访问,必须通过该类对外提供的方法访问。
可以防止外界进行不合理的赋值(如年龄赋值为负数),方便对属性值的控制
可参见“共享单车”或“公地悲剧”:
属性
1.成员变量设为private;
2.提供public的get/set方法作为访问器。
早年有书把field翻译为“属性”,现在field一般翻译为“成员变量”。成员变量不一定有方法器。
例:妖孽类有两个属性:name和species。
class 妖孽 {
private String name;
private String species;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSpecies() {
return species;
}
public void setSpecies(String species) {
this.species = species;
}
}
Eclipse中自动生成属性的快捷键:
代码中点击右键(快捷键Ctrl+Alt+S)
->Source
->Generate Getters and Setters...
->全选(或选择需要生成的字段/方法)
访问修饰符
(暂时可以不必全部理解,只需要关注private)
访问修饰符 | 自身 | 同包 | 同包 | 不同包 | 不同包 | |
---|---|---|---|---|---|---|
继承 | 不继承 | 继承 | 不继承 | |||
public | 大家用 | ● | ● | ● | ● | ● |
protected | 子类用,同包用 | ● | ● | ● | ● | X |
(default) | 同包用(不写) | ● | ● | ● | X | X |
private | 自己用 | ● | X | X | X | X |
成员变量·局部变量
成员变量:类里面定义的变量
局部变量:(1)方法中定义的变量;(2)复合语句中定义的变量for(int n : arr){...}
public class 变量 {
int 成员变量 = 1;
void m() {
int 局部变量 = 2;
System.out.println("m():" + 局部变量 + "," + 成员变量);
}
void m2() {
int 局部变量 = 3;
System.out.println("m2():" + 局部变量 + "," + 成员变量);
for (int i = 0; i < 10; i++) {
System.out.print(i + " ");
}
}
public static void main(String[] args) {
变量 t = new 变量();
t.m();
t.m2();
}
}
成员变量和局部变量不同之处:
成员变量 | 局部变量 | |
---|---|---|
定义位置 | 方法内存 | 方法内部,甚至语句中 |
作用范围 | 整个类都可以用 | 方法中可用,甚至语句范围内可用 |
生命周期 | 方法调用时诞生,方法结束消失 | 对象创建诞生,对象被回收消失 |
默认值 | 有默认值,规则和数组一样 | 无默认值,必须手动赋值 |
内存位置 | 栈(方法调用入栈,结束出栈) | 堆 |
方法(method)
方法,是类或对象行为的抽象。从功能上,方法类似于函数。
Java里的方法不能独立存在,必须写在类中。
传参:值传递
Java只有一种参数传递方式——值传递。
所谓值传递,就是将“实际参数”的副本传入方法,“实际参数”本身不受任何影响。
如经典的交换方法swap:
public class PassParameter {
static void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
System.out.println("内部:a = " + a + ", b = " + b);
}
public static void main(String[] args) {
int x = 100, y = 200;
System.out.println("交换前:x = " + x + ", y = " + y);
swap(x, y);
// 并没有交换成功
System.out.println("交换后:x = " + x + ", y = " + y);
}
}
↑swap得到的参数,只是实参x、y的复制品,实际上出现了4个变量。
运行结果:
交换前:x = 100, y = 200
内部:a = 200, b = 100
交换后:x = 100, y = 200
要想交换两数的值,可以将其封装到类中,类是引用类型,但传参的时候还是“值传递”。
不过,类变量中存放的其实是对象的引用,方法中对类变量进行修改,改变的不是变量的内存,而是其引用的实例对象的内容。
public class PassParameter2 {
static void swap(MyData data) {
int temp = data.a;
data.a = data.b;
data.b = temp;
}
public static void main(String[] args) {
MyData md = new MyData();
md.a = 100;
md.b = 200;
swap(md);
System.out.println("md.a = " + md.a + ", md.b = " + md.b);
}
}
class MyData {
int a;
int b;
}
注意,企图在函数中,对"类类型"的对象直接赋值是不行的,只能对其中的变量进行赋值。
所以不要意图通过方法调用对字符串进行赋值。
例如:
public class TestMethod {
void changeData(MyData2 md) {
md = new MyData2();
}
void changeStr(String s) {
s = "新";
}
public static void main(String[] args) {
TestMethod t = new TestMethod();
MyData2 md2 = null;
// 方法中对类对象赋值
t.changeData(md2);
System.out.println("md = " + md2);
// 方法中对字符串赋值
String s = "旧";
t.changeStr(s);
System.out.println(s);
}
}
class MyData2 {
}
运行结果:
md = null
旧
构造方法
构造方法也叫构造器,Constructor。
作用:初始化对象,通常是为成员变量赋初始值。
特点:1.没有返回值;2.方法名必须和类名一致。
其实构造方法的返回值是隐式的,就是当前类的对象。
new一个对象,实际上是调用其构造方法。
对象在构造方法调用前已经产生,但是需要通过构造方法返回。
public class 类和对象 {
public static void main(String[] args) {
Tiger c = new Tiger();
}
}
class Tiger {
public Tiger() {
System.out.println("---构造方法---");
}
}
运行结果:
---构造方法---
无参构造方法:
如果不手写构造方法,系统默认提供一个“无参构造方法”。
如果手写构造方法,系统不再提供无参构造方法。
构造方法自动生成:
自动生成的构造方法中往往会有一句super(),表示调用父类的无参构造方法,删掉也会调用。
class Tiger {
private String name;
public Tiger(String name) {
super();// 此代码可以不要,表示调用父类构造方法
// 成员变量和参数同名,根据就近原则,name使用参数,加this表示使用成员变量
this.name = name;
}
}
重载·overload
1.方法名相同
2.参数列表不同:
a)参数类型相同,个数不同
b)参数个数相同,类型不同
3.重载不管修饰符、返回类型等(方法调用可以不管返回值)
public class TestOverload {
static void m(int a, int b) {
System.out.println("m1");
}
static void m(int a, double b) {
System.out.println("m2");
}
public static void main(String[] args) {
m(1, 2);
m(1, 2.0);
}
}
静态·static
static可以用来修饰{类、成员变量、方法、代码块},表示这些成分属于“类本身”而不是“实例”。
静态变量
成员变量分为:
|-类变量(静态)
|-实例变量
实例可以有多个,每个实例可以有自己的数据;
类只有一个,static修饰的变量属于类,也只有一份,多个对象可以共享。
示例:数猫咪
public class Test静态变量 {
public static void main(String[] args) {
Cat c1 = null;
for (int i = 1; i <= 100; i++) {
c1 = new Cat();
c1.count++;
c1.countStatic++;
}
System.out.println(c1.count);
System.out.println(c1.countStatic);
Cat.countStatic++;// 静态变量可以直接通过类名调用
System.out.println(c1.countStatic);
}
}
class Cat {
static int countStatic = 1;
int count = 1;
}
静态方法
静态方法不属于对象,属于类。
静态分不需要new(实例化对象)就可以使用。
最著名的静态方法就是main方法。
静态方法的使用方式:类名.静态方法名(参数列表);
Array.sort(...)就是一个静态方法,没有new一个Arrays类出来,就可以使用之。
package ah;
public class Test静态方法 {
public static void main(String[] args) {
Dog.method静态方法();// 其他类中:类名调用
// 非静态方法(普通方法):new对象调用
Dog _dog = new Dog();
_dog.method普通方法();
}
}
class Dog {
void method普通方法() {
System.out.println("Dog:method普通方法");
}
static void method静态方法() {
System.out.println("Dog:method静态方法");
}
}
如果是在当前类中调用,类名可以省略。
public class Test静态方法2 {
void method普通方法() {
System.out.println("method普通方法");
}
static void method静态方法() {
System.out.println("method静态方法");
}
// -----------------------------
public static void main(String[] args) {
Test静态方法2.method静态方法();// 本类中:类名调用
method静态方法();// 本类:直接调用
// 即自己的非静态方法,也必须new
Test静态方法2 _self = new Test静态方法2();
_self.method普通方法();
}
}
静态代码块
普通代码块:类被创建(new)的时候执行,比构造方法还早。
静态代码块:类被使用的时候执行,比普通代码块还早。
|--当第一次使用本类时,静态代码块执行,且之后不会再执行。
public class Test静态代码块 {
public static void main(String[] args) {
Tiger _t = new Tiger();
}
}
class Tiger {
public Tiger() {
System.out.println("构造方法");
}
{
System.out.println("普通代码块");
}
static {
System.out.println("静态代码块");
}
}
输出结果:
静态代码块
普通代码块
构造方法
静态代码块的典型用途:一次性对静态成员变量进行赋值。
如:
public class Test静态代码块 {
public static void main(String[] args) {
System.out.println(Driver.os);
}
}
class Driver {
static String os;
static {
if ("Windows 10".equals(System.getProperty("os.name"))) {
os = "WinDriver";
} else {
os = "Driver";
}
}
}
Java基础教程——封装的更多相关文章
- Java基础教程:泛型基础
Java基础教程:泛型基础 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚 ...
- Java基础教程:多线程基础(4)——Lock的使用
Java基础教程:多线程基础(4)——Lock的使用 快速开始 Java 5中Lock对象的也能实现同步的效果,而且在使用上更加方便. 本节重点的2个知识点是:ReentrantLock类的使用和Re ...
- Java基础教程:面向对象编程[2]
Java基础教程:面向对象编程[2] 内容大纲 访问修饰符 四种访问修饰符 Java中,可以使用访问控制符来保护对类.变量.方法和构造方法的访问.Java 支持 4 种不同的访问权限. default ...
- Java基础教程(18)--继承
一.继承的概念 继承是面向对象中一个非常重要的概念,使用继承可以从逻辑和层次上更好地组织代码,大大提高代码的复用性.在Java中,继承可以使得子类具有父类的属性和方法或者重新定义.追加属性和方法. ...
- Java基础教程(12)--深入理解类
一.方法的返回值 当我们在程序中调用方法时,虚拟机将会跳转到对应的方法中去执行.当以下几种情况发生时,虚拟机将会回到调用方法的语句并继续向下执行: 执行完方法中所有的语句: 遇到return语句: ...
- Java基础教程:注解
Java基础教程:注解 本篇文章参考的相关资料链接: 维基百科:https://zh.wikipedia.org/wiki/Java%E6%B3%A8%E8%A7%A3 注解基础与高级应用:http: ...
- Java基础教程:网络编程
Java基础教程:网络编程 基础 Socket与ServerSocket Socket又称"套接字",网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个s ...
- Java基础教程(5)--变量
一.变量 1.变量的定义 正如上一篇教程<Java基础教程(4)--面向对象概念>中介绍的那样,对象将它的状态存在域中.但是你可能仍然有一些疑问,例如:命名一个域的规则和惯例是什么?除 ...
- Java基础教程:Lambda表达式
Java基础教程:Lambda表达式 本文部分内容引用自OneAPM:http://blog.oneapm.com/apm-tech/226.html 引入Lambda Java 是一流的面向对象语言 ...
随机推荐
- 绕过CDN查找真实IP的方法
正常情况下,通过cmd命令可以快速找到域名对应IP,最常见的命令如ping.nslookup.但很多站点出于用户体验和安全的角度,使用CDN加速,将域名解析到CDN,这时候就需要绕过CDN来查找真实I ...
- xlrd、xlwt常用命令
# -*- coding: utf-8 -*- import xlrd import xlwt from datetime import date,datetime def read_excel( ...
- Luogu P4546 [THUWC2017]在美妙的数学王国中畅游
题意 题意奇奇怪怪,这里就不写了. \(\texttt{Data Range:}1\leq n\leq 10^5,1\leq m\leq 2\times 10^5\) 题解 为什么你们都是卡在数学方面 ...
- 容器之间通讯方式\与pod关系
1.概述 k8s里面容器是存在于pod里面的,所以容器之间通讯,一般分为三种类型:1. pod内部容器之间 2. pod 与 pod 容器之间 3. pod 访问service服务 (1) pod内部 ...
- 基于SLF4J的MDC机制和Dubbo的Filter机制,实现分布式系统的日志全链路追踪
原文链接:基于SLF4J的MDC机制和Dubbo的Filter机制,实现分布式系统的日志全链路追踪 一.日志系统 1.日志框架 在每个系统应用中,我们都会使用日志系统,主要是为了记录必要的信息和方便排 ...
- .NET Core如何进行请求转发?
前言 冒个泡,近日,有关注我公众号的小伙伴私信我,遇到一个问题搞了很久没解决,此问题具有参考意义,这里跟大家分享下,希望对后续可能有需要的你能有所参考和帮助. 请求转发问题 内网环境跟外网隔离,现在外 ...
- AtCoder Beginner Contest 181 题解
总结 第一次 \(AK\ ABC\) 的比赛,发一个截图纪念一下 A - Heavy Rotation 题目大意 一个人一开始穿白衣服,一天后换成黑衣服,再过一天又换成白衣服,问第 \(n(n \le ...
- JS中this的指向性问题
一.this用于访问当前方法所属的对象,谁调用的方法,方法就属于谁 // 普通函数 let obj = { a : 12, fn() { console.log(this == obj); // tr ...
- 【SpringBoot】14. SpringBoot多环境配置
SpringBoot多环境配置 Spring Boot 1.5.19.RELEASE 假设项目中需要3个环境--开发.测试.生产 profile :代表的就是一个环境变量 语法结构:applicati ...
- 【QT】QtConcurrent::run()+QThreadPool实现多线程
往期链接: <QThread源码浅析> <子类化QThread实现多线程> <子类化QObject+moveToThread实现多线程> <继承QRunnab ...