1-2.基础面试总结

面向对象

面向对象(OOP)的三个特征:
1. 封装(根源和最根本的属性)
2. 继承
3. 多态
类与对象

面向对象的编程思想力图使在计算机语言中事物的描述与现实世界中该事物的本来面目尽可能地一致,类(Class)和对象(Object)就是面向对象方法的核心概念。是对某一类事物的描述,是抽象的、概念上的定义;对象是实际存在的该类事物的个体,是具体的,因为也称实例(Instance)。
如:
汽车设计图类,具体的一辆大众汽车为一个实例。
11类的定义
类可以将数据与函数封装在一起,其中数据表示类的属性,函数表示类的行为。即定义了类就要定义类的属性(类的成员变量)与行为(方法)(类的成员方法)。
如:
class Person {
int age;
void printAge() {
int age = 60;  // 函数内部重新定义的一个局部变量,区别与成员变量
System.out.println(“age is ” + age);
}
}
12对象的产生与使用
仅有汽车设计图是无法实现汽车功能的,只有产生了实际的汽车才行,同样想要实现类的属性和行为,必须创建具体的对象。
如:(
new关键字创建新对象)
Person p1 = new Person();
对象引用句柄p1(代表符合)是在栈中分配的一个变量,对象p1(实际对象)在堆中分配,原理同于数组。
注意:定义成员变量时,有默认值,局部变量时,必须初始化.
每个创建的对象都是有自己的生命周期的。
对象的3中生命周期:
第一种:

第二种:

第三种:(p1 = null;后,产生的Person对象不会变成垃圾,因为这个对象仍被p2所引用,
直到p2超出其作用域而无效

13对象的比较
2种方式可用与对象间的比较,‘==’equals()方法
==操作符用于比较两个变量的值(内存地址)是否相等,比如基本数据类型间的比较。
equal()方法用于比较2对象的内容是否一致。

程序代码:(==
class Compare {
public static void main(String[] args) {
String str1 = new String("abc");
String str2 = new String("abc");
String str3 = str1;
// str1
str2 是不同的对象,== 比较的是内存地址啦
System.out.println(str1 == str2);
System.out.println(str1 == str3);
}
}
结果:
false
true
图解:

程序代码:(equals())
public static void main(String[] args) {
String str1 = new String("abc");
String str2 = new String("abc");
String str3 = str1;
// equals()
比较的是值
System.out.println(str1.equals(str2));
System.out.println(str1.equals(str3));
}
}

14实现类的封装性
private:
正如人一样,人的身高不能随便修改,只能通过各种摄取营养的方法去修改这个属性。这是一种保护。那么怎样对一个类的成员实现保护呢?只需要在定义类成员(包括变量和方法)时,使用private 关键字说明这个成员的访问权限,private访问权限定义了类的私有成员,为高保护权限。只能被这个类的其他成员方法调用,不能被其他类中的方法所调用。
代码:
class Person {
private int age;
public void shout() {
System.out.println(age);  //
这一句没有错误,原因在上
}
}
class TestPerson {
public static void main(String[] args) {
new Person().age = -30;  //
报错,agePerson里的私有成员,不能在其他类中直// 接调用和访问。
}
}
结论:private 修饰的类成员,为该类的私有成员,只能在该类的内部访问。

public:
public 关键字修饰类成员,这些成员就是公共的,并可以在任意类中访问,当然,要在一个类外部访问这个类的成员必须用格式:对象.对象成员
为了实现良好的封装性,通常将类的成员变量声明为private,在通过public方法来对这个变量进行访问。
代码:
class Person {
private int age;
public viod setAge(int pAge) {
this.age = pAge;
}
pulic int getAge() {
return age;
}
}
public class TestPerson {
public static void main(String[] args) {
Person p1 = new Person();
p1.setAge(3);
System.out.println(p1.getAge());
}
}
对类成员变量private,提供一个多个public方法实现对该成员变量的访问或修改,即封装

封装目的:
1. 隐藏类的细节;
2. 让使用者只能通过事先定好的方法来访问数据,限制对属性的不合理操作;
3. 易于修改、维护、数据检查。

protected
包访问权限,只有处在同一包中的类可以访问该成员。

15构造函数
每创建一个Person对象,构造方法都会被调用一次。构造方法是public的,亦可为private(如单态设计模式)
根类名相同。没有返回值,没有return语句。可以重载。
使用构造器可以避免疏忽对变量的初始化,并且可以实现一次完成对类的所有实例对象的初始化。

如果声明类时,不写该类的构造函数,将默认产生一个无参构造,如果声明了有参构造,并且没有写默认构造器,将不会有默认构造器了。所以:
建议声明类时写上类的默认构造函数。

如果在声明Person对象时,必须指定姓名。可以去掉默认构造函数。并写一个有参数的参数函数代替之。
如:
class Person {
private String name;
public Person(String name) {
this.name = name;
}
}
创建Person类对象。因为没有了默认构造函数,声明类对象就必须这样:
Person p1 = new Person(“zhaoyubetter”);
16‘this’引用句柄
this 指当前对象(创建的对象即new出来的对象)
1. this 引用变量,指向调用这个方法对象(指对象自己);
如:
class Person {
private String name;
public Person(String name) {
this.name = name;
}
}

1. 通过this引用把当前的对象作为一个参数传递给其他的方法;
假设有一个容器类和一个部件类,在容器类的某个方法要创建部件类的实例对象,而部件类的构造方法要接收一个代表其所在容器的参数。
如:
class Container {
Componet comp;
public void addComponet() {
comp = new Componet(this);  //
this作为对象引用传递
}
}
class Componet {
Container myContainer;
public Componet(Container c) {
this.myContainer = c;
}
}
想象的内存图:(看代码,想象内存的变量。要活学)



1. 构造方法是在产生对象时被Java系统自动调用的,我们不能在程序中像其他调用其他方法一样去调用构造方法。但是我们可以通过this在一个构造方法里调用执行其他重载的构造方法。
如:
public class Person {
String name;
int age;
public Person(String name) {
this.name = name;
}
public Person(String name, int age) {
this(name);   //
通过this,执行第一个构造方法中的代码
this.age = age;
}
}
构造器,调用构造器用this
17      finalize() 方法
finalize() 方法是Object类的一个方法,任何一个类都从Object那继承了这个方法,finalize()方法是在对象被当成垃圾从内存中释放前调用,而不是在对象变成垃圾前调用,垃圾回收器的启用不由程序员控制,并无规律可循,并不是一产生垃圾,它就调用,不是很可靠的机制,即我们无法保证每个对象的finalize()最终被调用了。我们只需了解finalize()方法的作用即可
如:
class Person {
public void finalize() {
System.out.println(“the object is going.”);
}
public static void main(String[] args) {
new Person();
new Person();
new Person();
System.out.println(“the program is ending!”);
}
}
程序运行结果为:
the program is ending!
我们并没有看到垃圾回收器时finalize方法被调用。
17     System.gc()方法的作用
由于finalize()方法特点:如果程序某段运行时产生了大量垃圾,而finalize()方法也不回来被调用,这里我们就需要强制自动垃圾回收器来清理工作了,类似与垃圾桶满了,没有人来清理,我们可以主动打电话通知人来清理。
修改后代码:
class Person {
public void finalize() {
System.out.println(“the object is going.”);
}
public static void main(String[] args) {
new Person();
new Person();
new Person();
System.gc();  //
强制调用清理
System.out.println(“the program is ending!”);
}
}
程序运行结果为:
the object is going.
the object is going.
the object is going
the program is ending!
18 函数的参数传递
1.8.1 基本数据类型的参数传递
方法的形式参数就相当于方法中的局部变量,方法调用结束时被释放,并不会影响到主程序中同名的局部变量
程序代码:

class PassValue {
public static void main(String[] args) {
int x = 5;
change(x);
System.out.println(x);
}
public static void change(int x) {
x = 3;
}
}
内存分析:

结论:
基本数据类型的变量作为实参传递,并不能改变这个变量的值
String类似
1.8.2 引用数据类型的参数传递
对象的引用变量并不是对象本身,它们只是对象的句柄(名称),类似于一个人可以有个名称一样(如:英文名,中文名),一个对象可以有多个句柄(见:基础部分)
程序代码:
class PassRef {
int x;
public static void main(String[] args) {
PassRef obj = new PassRef();
obj.x = 5;
change(obj);
System.out.println(obj.x);
}
public static change(PassRef obj) { //
传递的为对象的引用 obj
System.out.println(obj.x);  // 
这里打印为5.
obj.x = 3;
}
}
内存分析:

结论:
Java语言在被给调用方法的参数赋值时,只采用传值的方式。所以,基本数据类型传递的是该数据的值本身,而引用数据类型传递的也是这个变量的值本身,即对象的引用(句柄),而非对象本身,但通过方法调用改变了对象的内容,但是对象的引用是不能改变的。
所以最终值发生了变量。数组 也属于引用数据类型。
比如:有人叫张三,他的小名叫小狗子,说小狗子怎么的,就是讲张三怎么的。

将代码转变一下:
class PassRef {
int x;
public static void main(String[] args) {
PassRef obj = new PassRef();
obj.x = 5;
change(obj);
System.out.println(obj.x);
}
public static change(PassRef obj) { //
传递的为对象的引用 obj
obj = new PassRef(); //
重新创建对象
//obj=2;
obj.x = 3;
}
}
内存自己分析下:
change()
方法执行了,但是没有起作用。这样的代码没有任何意义。
19 static关键字
1.9.1 静态变量
当我们编写一个类时,其实就是在描述其对象的属性和行为,并没有产生实质上的对象,只有通过new关键字才会产生出对象,这时系统才会分配内存空间给对象。
有时候我们希望无论是否产生了对象,某些特定的数据在内存空间里只有一份。类似于每个中国人的国家名称的变量,每个中国人都共享它。在该前面加上
static关键字,在内存中只存在一份,这就是静态成员变量。无需创建类的对象,直接用类名就可以引用。

注意:我们不能把任何方法体内的变量声明为静态
如:
fun {
static int i = 0;
}
static标识符修饰的变量,它们在类载入时创建,只要内存在,static变量就存在。
static只能是类的成员变量
1.9.2 静态方法
类似于静态成员,我们也可以创建静态方法,即不必创建对象就可以调用的方法。换句话说就是使该方法不必和对象绑在一起。呵呵。加static即可。
程序代码:
class Chinese {
static void sing() {
System.out.println("static
方法");
singOurCountry();   //
错误,无法从静态方法访问非静态方法。(原因:静态)
}
void singOurCountry() {
sing();   //
类中成员方法直接访问静态成员方法
}
}
public class TestChinese {
public static void main(String[] args) {
Chinese.sing();
Chinese ch1 = new Chinese();
ch1.sing();
ch1.singOurCountry();
}
}

类的静态成员称为类成员class members),
类的静态成员变量称为类属性class attributes),
类的静态成员方法称为类方法class methods
采用static关键字声明的属性和方法不属于类的某个实例对象。

使用类的静态方法时,注意:(其都是static原理
1. 在静态方法里只能直接调用其他的静态成员(包括变量和方法),而不能直接访问类中的非静态成员
2. 静态方法不能为任何方式引用thissuper关键字,thissuper的前提是创建类的对象。
3. main()方法是静态的。因此JVM在执行main方式时。不创建main方法所在类的实例对象。在main()中,不能直接访问该类的非静态成员,必须先创建类的对象。
了解原理:什么都简单了 易经
21 静态代码块
一个类中可以使用不包含在任何方法中的静态代码块(static block),当类被载入时,先执行静态代码块,且只被执行一次。静态块经常用来进行类属性的初始化。
如:
class StaticCode {
static String country; //
类属性(静态成员变量)
static {
country = “China”;
System.out.println(“StaticCode is loading”);
}
}
public class TestStaticCode {
static {
System.out.println(“TestStaticCode is loading!!!”);
}
public static void main(String[] args) {
System.out.println(“begin executing main method”);
new StaticCode();
new StaticCode();
}
}
结果为:
TestStaticCode is loading!!!
begin executing main method
StaticCode is loading
  (静态块只执行一次)
当一个程序中用到了其他的类,才会去转载那个类,并不是程序在启动时就装载所有的可能要用到的类
2.1.1 单态设计模式
设计模式是自爱大量的实践中总结和理论化之后的优选代码结构、编程风格以及解决问题的思考方式。设计模式就像是经典的棋谱。易
程序代码:
public class TestSingle {
private static final TestSingle onlyone = new TestSingle(); // static final
静态常量
public static TestSingle getTestSingle() { // 供外界访问的方法
return onlyone;
}
private TestSingle() {} //
构造方法私有,防止外界创建类对象
}
我们只能够通过getTestSingle()获得TestSingle的对象。这就是单态。
2.1.2 理解main方法的语法
由于Java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是public 的,又因为Java虚拟机在执行main()方法必须创建对象,所有该方法必须是static的,该方法接收一个String类型的数组参数,该数组中保存执行Java命令时传递给所运行的类的参数。
程序代码:
public class TestMain {
public static void main(String[] args) {
for(int i=0; i<args.length; i++) {
System.out.println(args[i]);
}
}
}
在命令行下输入 java TestMain first second
结果如下:
first
second


31 内部类
在一个类内部定义类,这就是嵌套类(nested classes),也叫内部类、内置类。
内部类可以直接访问嵌套它的类的成员,包括private成员,但是嵌套类的成员却不能被嵌套它的类直接访问
特殊的匿名内部类(见面向对象下部分)
3.1.1 类中定义内部类
内部类的使用范围,仅限于这个类的内部,内部类可以声明成privateprotected
程序代码:
class Outer {
int outor_i = 100;
void test() {
Inner in = new Inner();
in.display();
}
class Inner
{
void display() {
System.out.println(“display: out_i = ” + outer_i); //
直接访问外围类成员
}
}
}
public class InnerClassDemo {
public static void main(String[] args) {
Outer outer = new Outer();
outer.test();
}
}

内部类应用场合:
当一个类中的程序代码要用到另外一个类的实例对象,而另外一个类中的程序代码又要访问第一个类中的成员,将另外一个类做成第一个类的内部类。程序编码就容易的多,实际应用很广。
类似的内部类也可以声明为static类型的。呵呵。。根据static的特性。自己想吧。

如果内部类的成员变量与外部类的成员变量重名我们应该这样做:
如:
public class Outer {
private int size;
public class Inner {
private int size;
public void doStuff(int size) {
size++;  //
引用的是doStuff函数的形参
this.size++; // 引用的Inner类的成员变量
Outer.this.size++; // 引用的Outer类中的成员变量
}
}
}
3.1.2内部类如何被外部类引用
内部类可以通过创建对象从外部类之外访问,只要将内部类声明为public即可
程序代码:
class Outer {
private int size = 10;
public class Inner {
public void doStuff() {
System.out.println(++size);
}
}
}
public class TestInner {
public static void main(String[] args) {
Outer outer = new Outer();   //
先创建外围类对象
Outer.Inner inner = new out.new Inner(); // 创建内部类对象
inner.doStuff();
}
}
3.1.3方法中定义的内部类
嵌套类也可以定义在方法中。也可以在程序块的范围之内定义内部类。甚至是for循环内。
程序代码:
class Outer {
int outer_i = 10;
void test() {
for(int i=0; i<5; i++) {
class Inner {
void display() {
System.out.println(outer_i);
}
}
Inner inner = new Inner();
inner.display();
}
}
}

在方法中定义的内部类只能访问方法中的final类型的局部变量,final定义的局部变量是个常量,它的生命周期超出方法运行的生命周期。
如:
class InOut {
String str = new String(“between”);
public void method(final int iArgs) {
int it315 = 3;
class Bicycle {
public void say() {
System.out.println(str);
System.out.pritnln(iArg);
System.out.println(it315);  //
不能访问!
}
}
}
}
41 使用Java的文档注释
文档注释包含在‘/** … */’之间。开发者可以利用javadoc 工具将这些信息取出,然后转化成HTML说明文档。Java API 就是由javadoc生成的。
程序代码:
import java.io.*;

/**
 * Title: engineer
<br>
 * Description:
通过enginner类来说用Java中的文档注释<br>
 * Copyright:(c) 2009 www.ncsmsoft.com<br>
 * Company:ncsmsfot<br>
 * @author:zhaoyubetter
 * @version:1.0
*/

public class Engineer {
public String engineer_name;
/**
*
构造函数
         * @param name engineer的名称
*/
public Engineer(String name) {

}
/**
* repairing
方法的说明
         * @param sum 修理机器总数
* @param alltime 修理的总时间
* @return Repair的数量
*/
public Engineer(int sum,int alltime) {

}
}
在命令行模式下输入:javadoc –d engineer –version –author Engineer.java
-d
表示文件存放的目录
engineer 文件所存放的目录名
-version 要求javadoc程序在说明文件中加入版本信息
-author 加入作者信息
发布了46 篇原创文章 · 获赞 0 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章