So, considering they both do the same thing why should you opt to use
join instead of *? Here’s a few reasons:

* behaves totally differently when passed an integer argument:

12

[12]*3# => [1 2 1 2 1 2]

Personally, I’d expect this to be only behavior of such an operator
method and find the alternative one (with a string argument) to be
pretty much counter-intuitive.

It’s not always clear what * means without additional
context. Take a look at this short snippet:

12

# a and b are variablesa*b

Without some knowledge of a and b we cannot be certain what this
code is going to do. It’s hard even to speculate what the code is
going to do. Obviously better variable names would certainly help, but
the point still stands.

1

a.join(b)

While we still cannot be absolutely certain, it’s highly likely that a is
an Array and b is a String.

* does not carry much of a semantic value in it.

Unlike String#%, Array#* with a string argument carries pretty
much no meaning. It’s absolutely beyond me how this came into
existence. On the other hand the behavior of Array#* with an integer
argument is pretty reasonable. Here we see a classic example of the
notion that too much operator overloading can be a bad thing, leading
to some pretty unreadable code. An operator should be employed only
when it’s use would add clarity to the code, not take clarity away.

Array#* has one thing going for it, however – the fact that few
people know about its use as a substitute for Array#join. I hope
they realize that some unknown features are unknown for a reason –
because it’s bad idea to make use of them.

As usual I’m looking forward to hearing your thoughts here and on
Twitter!