Post

Java) regex / generics

Java) regex / generics

This post was migrated from Tistory. You can find the original here.

Regular expressions (regex)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Main {
    public static void main(String[] args) {
        String t = "^[0-9]*$";
        String res = "1597asd123".replaceAll(t, "yes");
        System.out.println(res);

        String res2 = "".replaceAll(t, "yes");
        System.out.println(res2);

        String res3 = "1235512".replaceAll(t, "yes");
        System.out.println(res3);
    }
}
result
1597asd123
yes
yes

[0-9]* : zero or more digits from 0 to 9.
^ X $ : both the start and the end must satisfy X.
\w : uppercase/lowercase letters + digits + “_”
\\w+@\\w+\\.\\w+(\\.\\w+)

  • In Java, \ is an escape sequence, so it processes whatever character follows it.
    That’s why we write \\w instead of \w.
  • In a regex, whatever character follows \ is treated as a literal character.
    In other words, \. == ., but since \ acts as an escape sequence in Java, we have to write it as \\..

In Java, just think of the regex \ as needing to be written twice.

Generics

1
2
3
4
5
6
7
8
9
10
11
public class Main {
    public static void main(String[] args) {
        Map<String, Integer> t = new HashMap();
        t.put("a", 1); t.put("b", 2);
        Iterator<Map.Entry<String, Integer>>it = t.entrySet().iterator();
        while(it.hasNext()){
            Map.Entry<String, Integer> entry = it.next();
            System.out.printf("%s, %d\n", entry.getKey(), entry.getValue());
        }
    }
}

Prefer using generics well over relying on casting.
In the code above, if you don’t specify the generic type on the Iterator, you’d need to cast with (Map.Entry<String, Integer>) it.next().

Type variables <T>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Main {
    public static void main(String[] args) {
        new Hello<Cat>(new Cat());
    }
}

class Hello<E> {
    public Hello(E o){
        System.out.println(o);
    }
}

class Cat{
    public String toString(){
        return "냐옹";
    }
}

냐옹

A class that takes a type variable is called a generic class.
The type variable T is treated as an instance variable, so static members cannot reference it.

After compilation, the generic type is erased and it becomes plain Hello.
ChatGPT says: Java generics are used as a tool for type checking at compile time, and the compiled bytecode does not contain the generic type information.

It increases type safety.
This means it prevents storing objects of an unintended type and reduces errors that could occur from casting to a different type than the original when retrieving an object.

Bounded generic classes

1
2
3
4
5
class Hello<E extends Dog> {
    public Hello(E o){
        System.out.println(o);
    }
}

Only the Dog class and its subclasses can be specified as the type.

1
2
3
4
5
6
7
8
9
class Hello<E extends Dog & Hi> {
    public Hello(E o){
        System.out.println(o);
    }
}

interface Hi{
    void hi();
}

You can also bound by an interface. Note that you use extends, not implements.
The code above requires a Dog type that also implements the Hi interface.

1
2
3
4
5
class Hello<E extends Dog & Cat> {
    public Hello(E o) {
        System.out.println(o);
    }
}

If you want to restrict the type to either Dog or Cat, you can’t write it like this.
& means it must satisfy both Dog and Cat, and since Dog and Cat aren’t in an inheritance relationship, this isn’t possible. (There doesn’t seem to be an “or” operator.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Hello<E extends Animal> {
    public Hello(E o) {
        System.out.println(o.CustomString());
    }
}

interface Animal{
    String CustomString();
}

class Cat implements Animal{
    public String CustomString() {
        return "냐옹";
    }
}

class Dog implements Animal{
    public String CustomString() {
        return "멍멍";
    }
}

As shown above, you can bound the type by a common type/interface.

1
2
3
4
5
6
7
8
9
class Dog implements Animal{
    public String CustomString() {
        return "멍멍";
    }
}

class Dog2 extends Dog implements Animal{

}

If a subclass has already inherited an implementation of an interface, there’s no error even if you don’t override it again.


Is there no way to override a method inside a constructor? Probably not.
A constructor runs when an object is created, and overriding happens at the class definition level.
I’m not sure if there’s a form where a method-within-a-method would make it possible.

This post is licensed under CC BY-NC 4.0 by the author.