面向对象进阶
封装private
封装的含义及特点:
在面向对象程式设计方法中,封装(Encapsulation)是指一种将抽象性函式接口的实现细节部分包装、隐藏起来的方法。
封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。
要访问该类的代码和数据,必须通过严格的接口控制。
封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。
适当的封装可以让程式码更容易理解与维护,也加强了程式码的安全性。
封装的优点:
1. 良好的封装能够减少耦合。
2. 类内部的结构可以自由修改。
3. 可以对成员变量进行更精确的控制。
4. 隐藏信息,实现细节。
实现封装
//1.使用private来限制属性访问
public class Person {
private String name;
private int age;
}
//2.对属性提供公有的getter和setter访问器
public class Person{
private String name;
private int age;
public int getAge(){
return age;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public void setName(String name){
this.name = name;
}
}
this关键字
含义:
this关键字代表当前对象的引用。
用法:
1、
this.属性名称
//访问类中的成员变量,用来区分成员变量和局部变量(解决重名问题)
2、
this.方法名称
//用来访问本类的成员方法
3、
this(参数列表);
//只能用于在一个构造方法中访问另一个构造方法,参数列表和那个构造方法一样,
//就是调用的那个构造方法,且只能是构造方法中的第一条
//所有构造方法都有隐式的this和super参数
静态static
用途:
方便在没有创建对象的情况下来进行调用(方法/变量)。
用static修饰的变量或方法不依赖对象进行访问,只需要类被加载了就可以通过类名进行访问。
static可以用来修饰类的成员方法,变量,还可以编写静态代码块来优化程序性能
1、静态方法
访问:类名.方法名(参数标签);
注意:
在静态方法中不能访问非静态成员变量和非静态成员方法,因为他们都依赖于对象才能进行访问,所以静态方法被调用时,可能他们还没有被创建。同理,在非静态成员方法中可以访问非静态成员变量和非静态成员方法。
实例构造器无法被隐藏或重写,不参与多态,因而可以做静态绑定。从这个意义上可以认为实例构造器是“静态”的,但这种用法与Java语言定义的“静态方法”是两码事。
2、静态变量
静态变量被所有对象共享,在内存中只有一个副本,各个对象拥有的副本互不影响
static成员变量初始化按定义顺序。
3、静态代码块
优化程序性能,可以置于类中任何位置,且可以同时存在多个,但只会随着类的加载执行一次
误区
1、java中static不会影响变量或方法的使用权限
2、当权限足够时是可以通过对象来访问静态成员变量和方法的
3、java中规定局部变量不允许使用静态符修饰。
常见笔试面试题
public class Test extends Base{
static{
System.out.println("test static");
}
public Test(){
System.out.println("test constructor");
}
public static void main(String[] args) {
new Test();
}
}
class Base{
static{
System.out.println("base static");
}
public Base(){
System.out.println("base constructor");
}
}
输出:
base static
test static
base constructor
test constructor
分析:在执行开始,先要寻找到main方法,因为main方法是程序的入口,但是在执行main方法之前,必须先加载Test类,而在加载Test类的时候发现Test类继承自Base类,因此会转去先加载Base类,在加载Base类的时候,发现有static块,便执行了static块。在Base类加载完成之后,便继续加载Test类,然后发现Test类中也有static块,便执行static块。在加载完所需的类之后,便开始执行main方法。在main方法中执行new Test()的时候会先调用父类的构造器,然后再调用自身的构造器。
2、
public class Test {
Person person = new Person("Test");
static{
System.out.println("test static");
}
public Test() {
System.out.println("test constructor");
}
public static void main(String[] args) {
new MyClass();
}
}
class Person{
static{
System.out.println("person static");
}
public Person(String str) {
System.out.println("person "+str);
}
}
class MyClass extends Test {
Person person = new Person("MyClass");
static{
System.out.println("myclass static");
}
public MyClass() {
System.out.println("myclass constructor");
}
}
输出:
test static
myclass static
person static
person Test
test constructor
person MyClass
myclass constructor
分析:
首先加载Test类,因此会执行Test类中的static块。接着执行new MyClass(),而MyClass类还没有被加载,因此需要加载MyClass类。在加载MyClass类的时候,发现MyClass类继承自Test类,但是由于Test类已经被加载了,所以只需要加载MyClass类,那么就会执行MyClass类的中的static块。在加载完之后,就通过构造器来生成对象。而在生成对象的时候,必须先初始化父类的成员变量,因此会执行Test中的Person person = new Person(),而Person类还没有被加载过,因此会先加载Person类并执行Person类中的static块,接着执行父类的构造器,完成了父类的初始化,然后就来初始化自身了,因此会接着执行MyClass中的Person person = new Person(),最后执行MyClass的构造器。
public class Test {
static{
System.out.println("test static 1");
}
public static void main(String[] args) {
}
static{
System.out.println("test static 2");
}
}
输出:
test static 1
test static 2
main()空语句,按顺序执行静态代码块。
包
作用:
为了更好地组织类,Java 提供了包机制,用于区别类名的命名空间
- 把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
- 如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
- 包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类
使用规则
- 包中java文件的定义:
在.java文件的首部, 必须编写类所属哪个包, 格式:
package 包名;
- 包的定义:
通常由多个单词组成, 所有单词的字母小写, 单词与单词之间使用.隔开 ,一般命名为“com. 公司名.项目名.模块名....”。
规范由来:
由于Java面向对象的特性,每名Java开发人员都可以编写属于自己的Java Package,为了保障每个Java Package命名的唯一性,在最新的Java编程规范中,要求开发人员在自己定义的包名前加上唯一的前缀。由于互联网上的域名称是不会重复的,所以多数开发人员采用自己公司在互联网上的域名称作为自己程序包的唯一前缀。例如:com.java.xxx
import关键字
import 包名.类名;
权限修饰符
/*
Java中有四种权限修饰符:
作用范围 public > protected > (default) > private
同一个类(我自己) YES YES YES YES
同一个包(我邻居) YES YES YES NO
不同包子类(我儿子) YES YES NO NO
不同包非子类(陌生人) YES NO NO NO
注意事项:(default)并不是关键字“default”,而是根本不写。
*/
代码块
普通代码块
在执行的流程中 出现的 代码块, 我们称其为普通代码块。
构造代码块
在类中的成员代码块, 我们称其为构造代码块,在每次对象创建时执行,执行在构造方法前。
静态代码块
在类中使用static修饰的成员代码块, 我们称其为静态代码块, 在类加载时执行。 每次程序启动到关闭 ,只会执行一次的代码块。
同步代码块
在后续多线程技术中学习。
面试题:
构造方法 与 构造代码块 以及 静态代码块的执行顺序:
静态代码块 --> 构造代码块 --> 构造方法
main方法详解
public static void main(String args[])
以上的各个参数的含义如下:
· public:表示公共的内容,可以被所有操作所调用
· static:表示方法是静态的,可以由类名称直接调用。java StaticDemo09
· void:表示没有任何的返回值操作
· main:系统规定好的方法名称。如果main写错了或没有,会报错:
NoSuchMethodError: main
· String[] args:字符串数组,接收参数的(接收命令行输入)
[]所有的参数在执行类的时候以空格进行分割
public class TestMain {
public static void main(String args[]){
System.out.println("打印main方法中的输入参数!");
for(int i=0;i<args.length;i++){
System.out.println(args[i]);
}
}
}
java TestMain 1 2 3 4 5 6 7
java TestMain "hello world","haha","eb"
java TestMain "hello world" "ha ha" " e b"
java TestMain hello a,hello b,hello c
错误:编码GBK的不可映射字符解决方法
-
输入命令时带上编译规则如:
javac TestMain.java–>javac -encoding GBK TestMain.java
2. 更改代码编码规则:
说明:系统jdk采用的编码是GBK,而代码编码用的utf-8所以出现错误。
编码格式:
ANSI:美国国家标准协会,系统预设的标准文字储存格式。简体中文编码GB2312,实际上它是ANSI的一个代码页936
UTF-8:通用字集转换格式,这是为传输而设计的编码,2进制,以8位为单元对Unicode进行编码,如果使用只能在同类位元组内支持8个位元的重要资料一类的旧式传输媒体,可选择UTF-8格式。
在UTF-8里,英文字符仍然跟ASCII编码一样,因此原先的函数库可以继续使用。而中文的编码范围是在0080-07FF之间,因此是2个字节表示(但这两个字节和GB编码的两个字节是不同的),用专门的Unicode处理类可以对UTF编码进行处理。