JAVA 8学习笔记-第四章
CHAPTER 4 Methods and Encapsulation
1. Designing Methods
public final void nap(int minutes) throws InterruptedException { //body}
access modifier: public, optional
optional specifier: final, optional
return type: void, required
method name: nap, required
parameter list: (int minutes), required, but can be empty ()
Optional exception list: throws InterruptedException, optional
method body: {}, required, can be empty{}
1) Access Modifier
private: can be called ONLY within the same class
default: can be called within the same class or by the classes within the same package, simply omitted
protected: can be called within the same class or by the classes within the same package or subclasses
public: can be called by any class
examle:
default void walk2(){} //compile error, default is not a access modifier
void public walk3(){} //compile error, return type can't be put before the access modifier
2) Optional Specifier
can have multiple optional specifier, can be put in any order
static: used for class method
final: used when a method is not allowed to be overridden by a subclass
abstract: used when not providing a method body
example:
public void final walk6(){} // compile error, optional specifier cann't be put after return type
final pulic void walk7(){} // compile OK, optional specifier can be put before the access modifier
3) Return Type
method must have a return type, when no value is returned , void is being used.
void: can have a return statement without value, or omit the return statement
other return types: must have a return statement with a primitive or object that matches the return type.
example:
void walk1(){}
void walk2(){return;}
int num(){return 2L;} // compile error, NOT assignable to the return type
4) Method Name
name rules as same as variable name's
- only contain letters, numbers, _ or $
- can NOT begin with numbers
- can NOT use reserved words like class, void, int, break....
5) Parameter List
- can be empty()
- multiple parameters separated by comma
6) Optional Exception List
- list many types of exceptions separated by comma
7) Method Body
code block which contains zero or more statements
8) Varargs
vararg parameter must be the last element in the method's parameter list.
when calling a method with a vararg parameter, you have two choices
- pass in a array, two ways: new int[2] or new int[] {2,3}
- list the elements of the array, and let JAVA create it for you
accessing the numbers of vararg just like accessing an array
example:
public static void walk(int num, int... nums){}
walk(1); // JAVA creates an array of length 0
walk(1,2); //JAVA creates an array of length 1
walk(1,2,3); //JAVA creates an array of length 2
walk(1, new int[] {4,5}); // pass in a array of length 2
walk(1, {4, 5}); // compile error, wrong way to create an array
walk(1, null); // JAVA treats null as reference of array
int num = nums[0]; // access number of vararg
9) Applying Access Modifier
- private
- default
- protected: protected member can be used without referring a variable within classes in the same package or subclasses, or by referring a variable which is a reference to the class in the same package or the SAME subclass where the reference appears.
- public
example:
package pond.shore;
public class Bird{
protected String text = "floating"; // protected access
protected void floatWater(){ // protected access
System.out.println(text):
}
}
package pond.swan;
import pond.shore.Bird; //different package
public class Swan extends Bird{ //create subclass
public void swim(){
floatWater(); // call protected member without referring a variable
System.out.println(text); // call protected member
}
public void helpOtherSwanSwim(){
Swan other = new Swan();
other.floatWater(); // call protected member through a variable referring to the same class Swan
System.out.println(other.text);
}
public void helpOtherBirdSwim(){
Bird other = new Bird(); // NOT refer to Swan
other.floatWater(); // does not compile, cause Bird is in a different package ( imported class Birdand compared to pond.shore.Bird ) and it doesn't inherit from Bird.
System.out.println(other.text); // not compile
}
public void helpOtherSwanFly(){
Bird other = new Swan();
other.floatWater(); // does not compile, cause object Swan is stored in Bird reference.
System.out.println(other.text); // not compile
}
}
package pond.goose;
import pond.swan.Swan;
public class Goose extends Swan{ //subclass of subclass of Bird
public void helpGooseFly(){
Swan swan = new Swan(); //NOT refer to Goose
swan.floatWater(); // not compile, reason same to Bird in the last example
System.out.println(swan.text); // not compile
}
public void helpGooseSwim(){
Goose goose = new Goose();
goose.floatWater(); // compile OK
System.out.println(goose.text); // compile OK
}
}
10) Static Methods and Fields
Static methods don't require an instance of the class, they are shared among all users of the class.
instance --- instance member, only data gets space in the stack, only one code copy. Only run when initialized, means never run if not initialized
class --- static member, only data gets space in the stack, only one code copy. Only run one time when the class is used. can be modified by instance member.
- a static member can NOT call an instance member (variable or method) directly, but can call it as an object member, like new Test().text
- a static member can call a static member by using classname
- an instance member can call an instance member by using reference variable (omit it when one method calling another in the same class)
- an instance member can call a static member by using the classname or reference variable
example:
class Order { // if there is public access modifier, this class should be saved in a separate file named Order.java.
static String result = "";
{ result += "c"; } // instance initializer
static
{ result += "u"; } // static initializer although it is at different line with keyword "static"
{ result += "r"; } // instance initializer
}
public class OrderDriver {
public static void main(String[] args) {
System.out.print(Order.result + " "); //static initializer is only run once
System.out.print(Order.result + " ");
new Order(); // trigger the instance initializer which can change the value of static member
new Order(); // trigger the instance initializer which can change the value of static member
System.out.print(Order.result + " ");
}} // result is "u u ucrcr"
static final --- constant, using all upper letters with underscore between words as name. NOT allowed to resign to another object
static initializer -- static{}, the only place where the static variables could possibly get initialized.
instance initializer -- {}
example:
private static int num1; //compile error, no initialization in the declaration line and static initializer
private static int num2;
static{ num2 =3; }
- try to avoid using static or instance initializer, cause it makes the code hard to read
- all the instance initialization can be done inside the constructor
- to use the static initializer to initialize static fields requiring more than one line of code.
static import are only used for importing static members, not the whole class.
regular imports are used for importing classes.
parameters has no business with static import.
example: import error
import static java.util.Collections.sort(ArrayList<String>); // compile error, parameters are not needed.
import static java.util.Collections.sort; // correct
import static java.util.Collections.*; // correct
example: name conflict.
import static statics.A.TYPE; //compile error
import static statics.B.TYPE; //compile error
can be solved as following:
import statics.A; //regular import
import statics.B;
int num1 = A.TYPE;
int num2 = B.TYPE;
2. Passing Data Among Methods
pass-by-value: a copy of variable (NOT value) is made and the method receives that copy (create a new reference to the same value). Assignments made in the method does NOT affect the caller.
example 1:
public static void main(String[] args){
int num = 4;
newnum(num);
System.out.println(num); //4
}
public static void newnum(int num){ //num is only a copy
num = 8
}
example 2:
public static void main(String[] args) {
StringBuilder name = new StringBuilder();
speak(name);
System.out.println(name); // Webby, they both points to the same StringBuilder.
}
public static void speak(StringBuilder s) {
s.append("Webby");
}
3. Overloading Methods
Methods with the same name but different type parameters (different type, more types or same types in different order)
example 1:
public void fly(int numMiles){}
public void fly(short numFeets){}
public boolean fly(){return false} // return types doesn't matter
void fly(){int numMiles, short numFeet} // access modifier doesn't matter
example 2:
public void fly(int[] lengths){}
public void fly(int... lengths){} // NOT compile, cause JAVA treats varargs as array, so they are considered to be the same method
the order to choose the right overloaded method,
-- the most specific parameter list it can find.
-- larger primitive type
-- autoboxed type
-- Varargs
JAVA only do one convention.
public void play(Long l){}
public void play(Long... l){}
play(4); // compile error, 4 can only be converted to long or Integer, can NOT be converted to Long
play(4L); //converted to Long
4. Creating Constructors
A constructor is a special method which matches the class name but has no return type.
Constructors are used when creating new object.
A constuctor is typically used to initialize instance variables.
The this keyword tells Java you want to reference to an instance variable.
when there is no name collision, this can be omitted
public class Bunny{
private int num;
private String color;
public Bunny(int newnum, String color){
num = newnum; // omit this
this.color = color; // this tells JAVA to refer to the instance variable
}
}
1) Constructors
The default constructor has an empty parameter list and an empty body.
It is only supplied when there is no constructors present.
Private consturctor prevents other classes from initializing the class.
Overloaded constructors often call each other. One common technique is to have each constructor add one parameter until getting to the constructor that does all the work. Why don't all other constructors cite the last constructor directly??
example:
public class Mouse {
private int numTeeth;
private int numWhiskers;
private int weight;
public Mouse(int weight) {
this(weight, 16); // calls constructor with 2 parameters
}
public Mouse(int weight, int numTeeth) {
this(weight, numTeeth, 6); // calls constructor with 3 parameters
}
public Mouse(int weight, int numTeeth, int numWhiskers) {
this.weight = weight;
this.numTeeth = numTeeth;
this.numWhiskers = numWhiskers;
}
public void print() {
System.out.println(weight + " " + numTeeth + " " + numWhiskers);
}
public static void main(String[] args) {
Mouse mouse = new Mouse(15);
mouse.print();
}
}
5. Final Fields
By the time the constructor completes, all final instance variables must have been set.
6. Order of Initialization
-- If there is superclass, initialize it first
-- Static variable declarations and static initializers
-- Instance variable declarations and instance initializers
-- constructors
The four rules apply only if an object is initialized.
If the class is referred without a new call, only rules 1 and 2 apply. The other two rules relates to instances and objects.
example:
public class YetMoreInitializationOrder { //result is 2 4 6 8 5
static { add(2);} // first, 2
static void add(int num) {System.out.print(num + " ");} //second
YetMoreInitializationOrder() {add(5);} // seventh, 5
static {add(4); } // third, 4
{ add(6); } // fifth, 6
static { new YetMoreInitializationOrder(); } // fourth, new starts instance initialization, but have to wait for others completing cause the body is calling constructor
{ add(8); } //sixth, 8
public static void main(String[] args) { }
}
7. Encapsulating Data
Encapsulation to the rescue. Encapsulation means we set up the class so only methods in the class can refer to the instance variables.
example: the data is private, setter and getter are public.
public class Swan {
private int numberEggs; // private
public int getNumberEggs() { // getter
return numberEggs;
}
public void setNumberEggs(int numberEggs) { // setter
if (numberEggs >= 0) // guard condition
this.numberEggs = numberEggs;
}
}
1) Rules for Javabeans naming Conventions
-- properties are private
-- getter method begin with is if the property is a boolean
-- getter method begin with get if the property is a not a boolean
-- the setter method begin with set
-- the method name must begin with is/get/set, with the first letter of property in uppercase, then followed by the rest of the property name
2) Creating Immutable Classes
One way to create immutable classes is to omit the setters and specify the initial value by constructors.
example 1:
public class ImmutableSwan {
private int numberEggs;
public ImmutableSwan(int numberEggs) { // immutable data type, when the object is created, it's immutable
this.numberEggs = numberEggs; }
public int getNumberEggs() { return numberEggs;}
}
example 2:
public class NotImmutable {
private StringBuilder builder;
public NotImmutable(StringBuilder b) { // mutable data type
builder = b;
}
public StringBuilder getBuilder() { return builder;}
}
public class test{
public static void main(String[] args){
StringBuilder sb = new StringBuilder("initial");
NotImmutable problem = new NotImmutable(sb); //pass-by-value, to create a new reference to the same value.
sb.append(" add");
StringBuilder gotBuilder = problem.getBuilder();
gotBuilder.append(" more");
System.out.println(sb); //"initial add more"
System.out.println(gotBuilder); //"initial add more"
System.out.println(problem.getBuilder); //"initial add more"
}}
To solve the problem in example 2.
-- to make a copy of the mutable object.
builder = new StringBuilder(b); // for the constructor
return new StringBuilder(builder); // for the getter
-- to return a immutable object for the getter
builder = new StringBuilder(b); // for the constructor
return builder.toString(); // for the getter
Encapsulation refers to preventing callers from changing instance variables directly.
Immutability refers to preventing callers from changing the instance vairables at all.
8. Writing Simple Lambdas
Functional Programming uses lambda expressions to write code. A lambda expression is a block of code that gets passed around.
It's like an anonymous method.
Deferred execution means that code is specified now but will run later.
1) Lambda Syntax
a -> a.canHop();
(Animal a) -> {return a.canHop();}
It means that Java will call an method with an Animal parameter that returns a boolean value that is a result of a.canHop().
-- the parenthese can only be omitted if there is a single parameter and its type is not explicitly stated.
-- the braces can only be omitted if there is a single statement, and the semicolon and return should be also omitted whild doing so.
(a, b) -> {int a =0; return 5;} //compile error, Java doesn't allow us to redeclare a local variable.
(a, b) -> {int c =0; return 5;} // ok
Java replies on context when figuring out what lambda expressions means.
We are passing lambda as the second paremeter of method print(). The method expects a CheckTrait as the second parameter. since we are passing a lambda instead, Java tries to match our lambda to that interface.
boolean test(Animal a)
-- since that interface's method takes an Animal, that means that lambda parameter has to be an Animal.
-- since the interface's method returns an boolean, we know lambda returns an boolean.
2) Predicates
Lambdas work with interfaces that have only one method. These are called function interfaces.
Java provide such an interface for us, called Predicate.
The predicate interface is in the package java.util.function.
public interface Predicate<T>{
boolean test(T t);
}
example 1:
import java.util.*;
import java.util.function.*; //import predicate interface
public class test{
public static void main(String[] args){
List<String> bunnies = new ArrayList<>();
bunnies.add("long ear");
bunnies.add("floppy");
bunnies.add("hoppy");
System.out.println(bunnies); // [long ear, floppy, hoppy]
bunnies.removeIf(s -> s.charAt(0) != 'h'); // define a predicate that takes a string and returns a boolean. the removeif does the rest.
System.out.println(bunnies); // [hoppy]
}}
example 2: print out "match"
import java.util.function.*;
public class Panda {
int age;
public static void main(String[] args) {
Panda p1 = new Panda();
p1.age = 1;
check(p1, p -> p.age < 5); // The lambda expression takes p (Panda) and returns a boolean (result of "p.age<5")
}
private static void check(Panda panda, Predicate<Panda> pred) {
String result = pred.test(panda) ? "match" : "not match"; // In my guess: boolean test(Panda p){ return (p.age<5);}
System.out.print(result); // match
}}
5. 单引号与双引号的区别
区别1:java中的单引号表示字符,java中的双引号是字符串。
区别2:单引号引的数据一般是char类型的;双引号引的数据 是String类型的。
区别3:java中单引号里面只能放一个字母或数字或符号;java中的双引号里面是0到多个字符构成。所以字符可以直接转换成字符串。字符串需要使用charAt(n) 来获取第几个字符。
char定义时用单引号,只能有一个字母,数字。char c='c';而String用双引号,可以是一个,也可能是多个字母,汉字等。就是所谓的字符串。String s="adsaf";
char只是一个基本类型,而String 可以是一个类,可以直接引用。比如char c='c';不能直接对c调用方法。String s="abc"; 这时可以调用s.charAt(0);等方法,因为String是类,这是就是对象的调用了